Files
AIEC-new/AIEC-server/js/main.js.modified
2025-10-17 09:31:28 +08:00

2766 lines
106 KiB
Plaintext
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.

/* ===== 云大阁网站JavaScript - 修复版 ===== */
// 全局变量
let chatCounter = 0;
let isDeepSearchActive = false;
let currentChatId = null;
let chatHistoryData = new Map(); // 存储聊天历史数据
let isOnlineMode = false; // 是否使用在线模式连接后端默认false使用本地存储
// DOM加载完成后执行
document.addEventListener('DOMContentLoaded', function() {
// 添加ESC键监听器以支持中断请求
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape' && window.isSubmitting) {
console.log('用户按下ESC键中断请求');
// 中断请求
if (window.currentAbortController) {
window.currentAbortController.abort();
window.currentAbortController = null;
}
// 重置状态
window.isSubmitting = false;
if (window.updateSendUI) {
window.updateSendUI(false);
}
// 显示提示
const statusText = document.querySelector('.status-text');
if (statusText) {
statusText.textContent = '已取消请求ESC';
statusText.style.color = '#dc3545';
setTimeout(() => {
statusText.textContent = 'Ready to submit!';
statusText.style.color = '';
}, 3000);
}
// 在聊天窗口添加提示
const chatContent = document.getElementById('chatContent');
const chatMessages = document.getElementById('chatMessages');
if (chatContent || chatMessages) {
const targetElement = chatMessages || chatContent;
const warningDiv = document.createElement('div');
warningDiv.className = 'ai-message';
warningDiv.style.cssText = 'background-color: #fff3cd; border: 1px solid #ffc107; color: #856404; padding: 10px; border-radius: 8px; margin: 10px 0;';
warningDiv.innerHTML = '⚠️ 请求已被ESC键取消。注意后端可能仍在处理建议稍等片刻再发送新请求。';
targetElement.appendChild(warningDiv);
setTimeout(() => {
warningDiv.style.transition = 'opacity 0.5s';
warningDiv.style.opacity = '0';
setTimeout(() => warningDiv.remove(), 500);
}, 5000);
}
}
});
// 只初始化核心功能,避免冲突
initSidebar();
initChat();
// initUserDropdown(); // 注释掉由auth-integration.js处理
initSearch();
initChatHistoryActions();
initTextRotator();
init3DTicker();
initDownloadModal();
initBackground(); // 初始化背景动画
initToolsDropdown(); // 初始化工具下拉菜单
// 确保初始状态下3D图片是显示的
const tickerSection = document.querySelector('.ticker-section');
const ticker3D = document.getElementById('ticker3D');
console.log('检查ticker-section:', tickerSection);
console.log('检查ticker3D:', ticker3D);
console.log('body是否有chat-mode类:', document.body.classList.contains('chat-mode'));
if (tickerSection) {
tickerSection.style.display = 'block';
tickerSection.style.visibility = 'visible';
tickerSection.style.opacity = '1';
console.log('设置ticker-section显示');
// 检查computed style
const computedStyle = window.getComputedStyle(tickerSection);
console.log('ticker-section computed display:', computedStyle.display);
console.log('ticker-section computed visibility:', computedStyle.visibility);
console.log('ticker-section computed height:', computedStyle.height);
} else {
console.error('未找到ticker-section元素');
}
// 设置侧边栏默认状态 - 默认折叠
const sidebar = document.getElementById('sidebar');
if (sidebar) {
// 所有设备默认折叠状态
sidebar.classList.add('collapsed');
}
// 页面加载完自动聚焦到输入框
const messageInput = document.getElementById('messageInput');
if (messageInput) {
setTimeout(() => {
messageInput.focus();
}, 500);
}
// 初始化聊天管理器监听器
initChatManagerListeners();
// 等待 ChatManager 初始化完成后再加载
const waitForChatManager = () => {
if (window.chatManager && window.chatManager.initialized) {
console.log('[Main] ChatManager 已初始化,开始加载聊天历史');
// 加载用户的聊天历史
loadUserChatHistory();
// 恢复当前对话
setTimeout(() => {
console.log('[Main] 检查是否需要恢复对话...');
console.log('[Main] chatManager.currentChatId:', window.chatManager.currentChatId);
if (window.chatManager.currentChatId) {
console.log('[Main] 开始恢复上次的对话:', window.chatManager.currentChatId);
loadChatHistory(window.chatManager.currentChatId);
// 高亮侧边栏中的当前对话
const chatItem = document.querySelector(`[data-chat-id="${window.chatManager.currentChatId}"]`);
if (chatItem) {
chatItem.classList.add('active');
console.log('[Main] 已高亮当前对话项');
} else {
console.log('[Main] ⚠️ 未找到对应的侧边栏对话项');
}
} else {
console.log('[Main] 没有需要恢复的对话');
}
}, 50);
} else {
console.log('[Main] 等待 ChatManager 初始化...');
setTimeout(waitForChatManager, 100);
}
};
waitForChatManager();
// 监听用户登录状态变化
initUserChangeListener();
// 初始化Markdown渲染器和工具栏
if (window.markdownRenderer) {
window.markdownRenderer.initCodeCopyButtons();
// 确保工具栏被初始化
const welcomeToolbar = document.getElementById('markdownToolbar');
const welcomeInput = document.getElementById('messageInput');
if (welcomeToolbar && welcomeInput) {
welcomeToolbar.innerHTML = window.markdownRenderer.createToolbar();
welcomeToolbar.style.display = 'flex';
window.markdownRenderer.attachToolbarEvents(welcomeToolbar, welcomeInput);
}
}
// 初始化工具下拉菜单
initToolsDropdown();
console.log('云大阁网站已加载完成');
});
/* ===== 侧边栏功能 - 复刻duijie.html简单逻辑 + yundage-keyong1的tooltip ===== */
function toggleSidebar() {
document.getElementById('sidebar').classList.toggle('collapsed');
}
function initSidebar() {
// Logo点击切换事件
const logoMenuItem = document.getElementById('logoMenuItem');
if (logoMenuItem) {
logoMenuItem.addEventListener('click', function(e) {
toggleSidebar();
e.stopPropagation();
});
}
// 新建对话按钮事件
const newChatBtn = document.getElementById('newChatBtn');
if (newChatBtn) {
newChatBtn.addEventListener('click', function() {
console.log('新建对话按钮被点击');
startNewChat();
});
}
// 下载APP按钮事件
const downloadAppBtn = document.getElementById('downloadAppBtn');
if (downloadAppBtn) {
downloadAppBtn.addEventListener('click', function() {
console.log('下载APP按钮被点击');
initDownloadModal();
});
}
// 初始化tooltip定位
initTooltipPositioning();
}
// ChatGPT风格的tooltip定位 - 将tooltip移动到body避免遮挡
function initTooltipPositioning() {
const sidebar = document.getElementById('sidebar');
if (!sidebar) return; // 如果sidebar不存在直接返回
const tooltipWrappers = sidebar.querySelectorAll('.tooltip-wrapper');
tooltipWrappers.forEach(wrapper => {
const tooltipText = wrapper.querySelector('.tooltip-text');
if (!tooltipText) return;
let floatingTooltip = null;
wrapper.addEventListener('mouseenter', function() {
if (sidebar.classList.contains('collapsed')) {
// 创建独立的tooltip元素添加到body
floatingTooltip = document.createElement('div');
floatingTooltip.textContent = tooltipText.textContent;
floatingTooltip.className = 'floating-tooltip';
floatingTooltip.style.cssText = `
position: fixed;
background-color: #333;
color: #fff;
text-align: center;
padding: 6px 10px;
border-radius: 6px;
white-space: nowrap;
font-size: 13px;
z-index: 999999;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
border: 1px solid rgba(255, 255, 255, 0.1);
pointer-events: none;
`;
// 获取wrapper的位置
const rect = wrapper.getBoundingClientRect();
// 设置tooltip位置
floatingTooltip.style.left = (rect.right + 10) + 'px';
floatingTooltip.style.top = (rect.top + rect.height / 2) + 'px';
floatingTooltip.style.transform = 'translateY(-50%)';
// 添加到body
document.body.appendChild(floatingTooltip);
}
});
wrapper.addEventListener('mouseleave', function() {
if (floatingTooltip) {
document.body.removeChild(floatingTooltip);
floatingTooltip = null;
}
});
});
}
/* ===== 聊天功能 ===== */
function initChat() {
const sendBtn = document.getElementById('sendBtn');
const messageInput = document.getElementById('messageInput');
const chatMessages = document.getElementById('chatMessages');
const deepSearchToggle = document.getElementById('deepSearchToggle');
const newChatBtn = document.getElementById('newChatBtn');
const voiceBtn = document.getElementById('voiceBtn');
// 聊天模式元素
const chatModeSendBtn = document.getElementById('chatModeSendBtn');
const chatModeMessageInput = document.getElementById('chatModeMessageInput');
if (!sendBtn || !messageInput || !chatMessages) {
console.error('关键聊天元素未找到');
return;
}
// 初始化发送按钮状态
updateSendButtonState();
// 发送消息(支持停止功能)
sendBtn.addEventListener('click', function(e) {
e.preventDefault();
if (window.isSubmitting) {
// 停止操作
console.log('用户点击停止按钮');
if (window.currentAbortController) {
window.currentAbortController.abort();
window.currentAbortController = null;
}
window.isSubmitting = false;
updateSendUI(false);
// 显示提示信息
const statusText = document.querySelector('.status-text');
if (statusText) {
statusText.textContent = '已取消请求';
statusText.style.color = '#dc3545';
setTimeout(() => {
statusText.textContent = 'Ready to submit!';
statusText.style.color = '';
}, 3000);
}
// 在聊天窗口添加提示
const chatContent = document.getElementById('chatContent');
if (chatContent) {
const warningDiv = document.createElement('div');
warningDiv.className = 'ai-message';
warningDiv.style.cssText = 'background-color: #fff3cd; border: 1px solid #ffc107; color: #856404; padding: 10px; border-radius: 8px; margin: 10px 0;';
warningDiv.innerHTML = '⚠️ 请求已取消。注意:后端可能仍在处理,建议稍等片刻再发送新请求。';
chatContent.appendChild(warningDiv);
setTimeout(() => {
warningDiv.style.transition = 'opacity 0.5s';
warningDiv.style.opacity = '0';
setTimeout(() => warningDiv.remove(), 500);
}, 5000);
}
} else {
// 发送操作
console.log('发送按钮被点击');
sendMessage();
}
});
// 回车发送消息Shift+Enter换行
messageInput.addEventListener('keydown', function(e) {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
sendMessage();
}
});
// 监听输入框变化,更新发送按钮状态和自动调整高度
messageInput.addEventListener('input', function() {
updateSendButtonState();
autoResizeTextarea(this);
});
// 深度检索切换
if (deepSearchToggle) {
deepSearchToggle.addEventListener('click', function() {
console.log('深度检索按钮被点击');
toggleDeepSearch();
});
}
// 删除重复的事件监听器绑定,前面已经绑定过了
// 语音按钮(暂时无功能)
if (voiceBtn) {
voiceBtn.addEventListener('click', function() {
console.log('语音按钮被点击');
// 这里可以添加语音功能
});
}
// 聊天模式输入框事件监听器
if (chatModeSendBtn && chatModeMessageInput) {
// 发送消息(支持停止功能)
chatModeSendBtn.addEventListener('click', function(e) {
e.preventDefault();
if (window.isSubmitting) {
// 停止操作
console.log('用户点击停止按钮(聊天模式)');
if (window.currentAbortController) {
window.currentAbortController.abort();
window.currentAbortController = null;
}
window.isSubmitting = false;
updateSendUI(false);
// 在聊天窗口添加提示
addMessage('⚠️ 请求已取消。注意:后端可能仍在处理,建议稍等片刻再发送新请求。', 'system');
} else {
// 发送操作
sendChatModeMessage();
}
});
// 回车发送消息
chatModeMessageInput.addEventListener('keydown', function(e) {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
sendChatModeMessage();
}
});
// 监听输入框变化
chatModeMessageInput.addEventListener('input', function() {
updateChatModeSendButtonState();
autoResizeTextarea(this);
});
}
// 更新发送按钮状态
function updateSendButtonState() {
const messageInput = document.getElementById('messageInput');
const sendBtn = document.getElementById('sendBtn');
const sendIcon = document.getElementById('sendIcon');
if (messageInput && sendBtn && sendIcon) {
const hasText = messageInput.value.trim().length > 0;
sendIcon.style.opacity = hasText && !window.isSubmitting ? '1' : '0.3';
}
}
// 更新发送UI状态改造为停止按钮
function updateSendUI(isLoading) {
const sendIcon = document.getElementById('sendIcon');
const loadingSpinner = document.getElementById('loadingSpinner');
const statusText = document.querySelector('.status-text');
const messageInput = document.getElementById('messageInput');
const sendBtn = document.getElementById('sendBtn');
// 同时更新聊天模式的UI
const chatModeSendIcon = document.getElementById('chatModeSendIcon');
const chatModeLoadingSpinner = document.getElementById('chatModeLoadingSpinner');
const chatModeMessageInput = document.getElementById('chatModeMessageInput');
const chatModeSendBtn = document.getElementById('chatModeSendBtn');
if (isLoading) {
// 首页:显示红色停止图标
if (loadingSpinner) {
loadingSpinner.style.setProperty('display', 'none', 'important');
}
if (sendIcon) {
sendIcon.style.display = 'block';
sendIcon.innerHTML = `
<rect x="6" y="6" width="12" height="12" fill="#dc3545"/>
`;
sendIcon.style.opacity = '1';
}
if (sendBtn) {
sendBtn.disabled = false;
sendBtn.title = '点击停止或按ESC键';
}
if (statusText) statusText.textContent = 'AI is thinking...';
if (messageInput) messageInput.disabled = true;
// 聊天模式:同样显示红色停止图标
if (chatModeLoadingSpinner) {
chatModeLoadingSpinner.style.setProperty('display', 'none', 'important');
}
if (chatModeSendIcon) {
chatModeSendIcon.style.display = 'block';
chatModeSendIcon.innerHTML = `
<rect x="6" y="6" width="12" height="12" fill="#dc3545"/>
`;
chatModeSendIcon.style.opacity = '1';
}
if (chatModeSendBtn) {
chatModeSendBtn.disabled = false;
chatModeSendBtn.title = '点击停止或按ESC键';
}
if (chatModeMessageInput) chatModeMessageInput.disabled = true;
} else {
// 首页:恢复发送图标
if (sendIcon) {
sendIcon.style.display = 'block';
sendIcon.innerHTML = `
<path d="m3 3 3 9-3 9 19-9Z"/>
<path d="m6 12 13 0"/>
`;
}
if (loadingSpinner) {
loadingSpinner.style.display = 'none';
}
if (sendBtn) {
sendBtn.disabled = false;
sendBtn.title = '发送消息';
}
if (statusText) statusText.textContent = 'Ready to submit!';
if (messageInput) messageInput.disabled = false;
updateSendButtonState();
// 聊天模式:恢复发送图标
if (chatModeSendIcon) {
chatModeSendIcon.style.display = 'block';
chatModeSendIcon.innerHTML = `
<path d="m3 3 3 9-3 9 19-9Z"/>
<path d="m6 12 13 0"/>
`;
}
if (chatModeLoadingSpinner) {
chatModeLoadingSpinner.style.display = 'none';
}
if (chatModeSendBtn) {
chatModeSendBtn.disabled = false;
chatModeSendBtn.title = '发送消息';
}
if (chatModeMessageInput) chatModeMessageInput.disabled = false;
updateChatModeSendButtonState();
}
}
// 暴露到全局以便其他模块使用
window.updateSendUI = updateSendUI;
// 聊天模式按钮状态管理
function updateChatModeSendButtonState() {
const chatModeMessageInput = document.getElementById('chatModeMessageInput');
const chatModeSendIcon = document.getElementById('chatModeSendIcon');
if (chatModeMessageInput && chatModeSendIcon) {
const hasText = chatModeMessageInput.value.trim().length > 0;
chatModeSendIcon.style.opacity = hasText && !window.isSubmitting ? '1' : '0.3';
}
}
// 聊天模式发送消息
async function sendChatModeMessage() {
const chatModeMessageInput = document.getElementById('chatModeMessageInput');
const message = chatModeMessageInput.value.trim();
if (!message || window.isSubmitting) {
console.log('消息为空或正在发送中,不发送');
return;
}
console.log('聊天模式发送消息:', message);
// 设置发送状态
window.isSubmitting = true;
updateChatModeSendUI(true);
// 如果是第一条消息且没有当前聊天ID创建新聊天
if (!currentChatId) {
// 立即创建新的聊天会话
if (window.chatManager) {
currentChatId = window.chatManager.createChat(message);
window.chatManager.currentChatId = currentChatId;
// 立即添加到侧边栏
const chatTitle = message.length > 20 ? message.substring(0, 20) + '...' : message;
addChatToSidebar(currentChatId, chatTitle, true);
}
}
// 保存当前聊天ID避免切换聊天记录时被改变
const targetChatId = currentChatId;
// 添加用户消息
await addMessage(message, 'user');
// 清空输入框
chatModeMessageInput.value = '';
autoResizeTextarea(chatModeMessageInput);
updateChatModeSendButtonState();
// 调用后端API获取AI回复
try {
// 判断是否使用流式响应
const useStream = true; // 可以根据需要调整
if (useStream) {
// 流式响应
let aiMessageId = null;
let aiContent = '';
// 获取工具设置
const toolsSettings = window.getToolsSettings ? window.getToolsSettings() : { deepResearch: false, showThinking: false };
const isDeepResearch = toolsSettings.deepResearch;
const showThinking = toolsSettings.showThinking;
// 创建状态显示组件
let statusDisplay = null;
if (window.StreamStatusDisplay) {
// 在消息区域之前创建状态显示容器
const statusContainer = document.createElement('div');
statusContainer.id = `status-${targetChatId}-${Date.now()}`;
chatMessages.appendChild(statusContainer);
statusDisplay = new window.StreamStatusDisplay(statusContainer);
}
const abortController = await window.ChatAPIService.sendMessageStream(
window.currentAbortController = abortController; // 保存到全局以便中断
{
message: message,
conversationId: targetChatId, // 使用保存的targetChatId
mode: isDeepSearchActive ? 'research' : 'chat',
deepResearch: isDeepResearch,
showThinking: showThinking
},
// onMessage: 接收消息片段
(content) => {
// 只有当前聊天ID与目标ID一致时才更新UI
if (currentChatId === targetChatId) {
aiContent += content;
if (aiMessageId) {
// 更新已存在的消息
updateMessageContent(aiMessageId, aiContent);
} else {
// 创建新消息
aiMessageId = Date.now().toString();
addStreamMessage(aiContent, 'ai', aiMessageId);
}
} else {
// 如果已切换到其他聊天仅累积内容但不更新UI
aiContent += content;
}
},
// onComplete: 完成回调
async (data) => {
console.log('流式响应完成:', data);
// 使用保存的targetChatId保存AI回复到正确的聊天记录
if (window.chatManager && targetChatId) {
// 保存到目标聊天记录
const originalChatId = window.chatManager.currentChatId;
window.chatManager.currentChatId = targetChatId;
window.chatManager.addMessage(aiContent, 'ai');
// 如果当前聊天已切换,不需要恢复
if (currentChatId !== targetChatId) {
window.chatManager.currentChatId = originalChatId;
}
}
// 恢复发送状态
window.isSubmitting = false;
updateChatModeSendUI(false);
},
// onError: 错误回调
(error) => {
console.error('流式响应错误:', error);
addMessage(`抱歉,发生了错误:${error.message}`, 'ai');
window.isSubmitting = false;
updateChatModeSendUI(false);
},
// onThinking: 思考过程回调
showThinking ? (thinking) => {
console.log('思考过程:', thinking);
// 显示思考过程
if (!document.getElementById('thinking-message')) {
const thinkingDiv = document.createElement('div');
thinkingDiv.id = 'thinking-message';
thinkingDiv.className = 'thinking-process';
thinkingDiv.innerHTML = `
<div class="thinking-label">🤔 思考过程:</div>
<div class="thinking-content"></div>
`;
chatMessages.appendChild(thinkingDiv);
chatMessages.scrollTop = chatMessages.scrollHeight;
}
const thinkingContent = document.querySelector('#thinking-message .thinking-content');
if (thinkingContent) {
thinkingContent.textContent += thinking;
}
} : null,
// onStatus: 状态更新回调(新增)
(status) => {
if (statusDisplay) {
statusDisplay.updateStatus(status);
}
}
);
} else {
// 同步响应
const response = await window.ChatAPIService.sendMessage({
message: message,
conversationId: targetChatId, // 使用保存的targetChatId
mode: isDeepSearchActive ? 'research' : 'chat'
});
if (response.success) {
// 更新会话ID如果是新会话
if (response.conversationId && !targetChatId) {
const newChatId = response.conversationId;
// 只有当前聊天与目标一致时才更新全局变量
if (currentChatId === targetChatId) {
currentChatId = newChatId;
}
if (window.chatManager) {
window.chatManager.currentChatId = newChatId;
}
// 添加新会话到侧边栏
const chatTitle = message.length > 20 ? message.substring(0, 20) + '...' : message;
addChatToSidebar(newChatId, chatTitle, true);
}
// 使用addMessageToChat统一处理AI回复
await addMessageToChat(response.answer, 'ai', targetChatId);
} else {
// 使用addMessageToChat统一处理错误消息
await addMessageToChat('抱歉,获取回复时出现错误。', 'ai', targetChatId);
}
// 恢复发送状态
window.isSubmitting = false;
updateChatModeSendUI(false);
}
} catch (error) {
console.error('发送消息失败:', error);
// 使用addMessageToChat统一处理错误消息
await addMessageToChat(`抱歉,发生了错误:${error.message}`, 'ai', targetChatId);
window.isSubmitting = false;
updateChatModeSendUI(false);
}
// 重新聚焦输入框
chatModeMessageInput.focus();
}
// 聊天模式UI状态更新直接调用统一的updateSendUI
function updateChatModeSendUI(isLoading) {
updateSendUI(isLoading);
}
// 暴露到全局
window.updateChatModeSendUI = updateChatModeSendUI;
// 自动调整输入框高度参考ChatGPT/DeepSeek
function autoResizeTextarea(textarea) {
// 检查是否是欢迎模式的输入框(有特殊的最小高度)
if (textarea.id === 'messageInput') {
// 欢迎模式输入框保持固定高度124px不自动调整
return;
}
// 聊天模式输入框自动调整高度
// 重置高度以获取正确的scrollHeight
textarea.style.height = '40px';
// 计算新高度
const newHeight = Math.min(textarea.scrollHeight, 120); // 最大120px
textarea.style.height = newHeight + 'px';
// 如果内容超过最大高度,显示滚动条
if (textarea.scrollHeight > 120) {
textarea.style.overflowY = 'auto';
} else {
textarea.style.overflowY = 'hidden';
}
}
async function sendMessage() {
const message = messageInput.value.trim();
if (!message || window.isSubmitting) {
console.log('消息为空或正在发送中,不发送');
return;
}
console.log('发送消息:', message);
// 设置发送状态
window.isSubmitting = true;
updateSendUI(true);
// 显示聊天容器
showChatContainer();
// 如果是第一条消息且没有当前聊天ID创建新聊天
if (!currentChatId) {
// 立即创建新的聊天会话
if (window.chatManager) {
currentChatId = window.chatManager.createChat(message);
window.chatManager.currentChatId = currentChatId;
// 立即添加到侧边栏
const chatTitle = message.length > 20 ? message.substring(0, 20) + '...' : message;
addChatToSidebar(currentChatId, chatTitle, true);
}
}
// 保存当前聊天ID避免切换聊天记录时被改变
const targetChatId = currentChatId;
// 添加用户消息使用固定的chatId
await addMessageToChat(message, 'user', targetChatId);
// 清空输入框并重置高度
messageInput.value = '';
// 欢迎模式输入框保持124px高度
if (messageInput.id === 'messageInput') {
messageInput.style.height = '124px';
} else {
messageInput.style.height = '40px';
}
updateSendButtonState();
// 调用后端API获取AI回复
try {
// 判断是否使用流式响应
const useStream = true; // 可以根据需要调整
if (useStream) {
// 流式响应
let aiMessageId = null;
let aiContent = '';
// 获取工具设置
const toolsSettings = window.getToolsSettings ? window.getToolsSettings() : { deepResearch: false, showThinking: false };
const isDeepResearch = toolsSettings.deepResearch;
const showThinking = toolsSettings.showThinking;
// 创建状态显示组件
let statusDisplay = null;
if (window.StreamStatusDisplay) {
// 在消息区域之前创建状态显示容器
const statusContainer = document.createElement('div');
statusContainer.id = `status-${targetChatId}-${Date.now()}`;
chatMessages.appendChild(statusContainer);
statusDisplay = new window.StreamStatusDisplay(statusContainer);
}
const abortController = await window.ChatAPIService.sendMessageStream(
window.currentAbortController = abortController; // 保存到全局以便中断
{
message: message,
conversationId: targetChatId, // 使用保存的targetChatId
mode: isDeepSearchActive ? 'research' : 'chat',
deepResearch: isDeepResearch,
showThinking: showThinking
},
// onMessage: 接收消息片段
(content) => {
// 只有当前聊天ID与目标ID一致时才更新UI
if (currentChatId === targetChatId) {
aiContent += content;
if (aiMessageId) {
// 更新已存在的消息
updateMessageContent(aiMessageId, aiContent);
} else {
// 创建新消息
aiMessageId = Date.now().toString();
addStreamMessage(aiContent, 'ai', aiMessageId);
}
} else {
// 如果已切换到其他聊天仅累积内容但不更新UI
aiContent += content;
}
},
// onComplete: 完成回调
async (data) => {
console.log('流式响应完成:', data);
// 使用保存的targetChatId保存AI回复到正确的聊天记录
if (window.chatManager && targetChatId) {
// 保存到目标聊天记录
const originalChatId = window.chatManager.currentChatId;
window.chatManager.currentChatId = targetChatId;
window.chatManager.addMessage(aiContent, 'ai');
// 如果当前聊天已切换,不需要恢复
if (currentChatId !== targetChatId) {
window.chatManager.currentChatId = originalChatId;
}
}
// 恢复发送状态
window.isSubmitting = false;
updateSendUI(false);
},
// onError: 错误回调
(error) => {
console.error('流式响应错误:', error);
addMessage(`抱歉,发生了错误:${error.message}`, 'ai');
window.isSubmitting = false;
updateSendUI(false);
},
// onThinking: 思考过程回调
showThinking ? (thinking) => {
console.log('思考过程:', thinking);
// 显示思考过程
if (!document.getElementById('thinking-message')) {
const thinkingDiv = document.createElement('div');
thinkingDiv.id = 'thinking-message';
thinkingDiv.className = 'thinking-process';
thinkingDiv.innerHTML = `
<div class="thinking-label">🤔 思考过程:</div>
<div class="thinking-content"></div>
`;
chatMessages.appendChild(thinkingDiv);
chatMessages.scrollTop = chatMessages.scrollHeight;
}
const thinkingContent = document.querySelector('#thinking-message .thinking-content');
if (thinkingContent) {
thinkingContent.textContent += thinking;
}
} : null,
// onStatus: 状态更新回调(新增)
(status) => {
if (statusDisplay) {
statusDisplay.updateStatus(status);
}
}
);
} else {
// 同步响应
const response = await window.ChatAPIService.sendMessage({
message: message,
conversationId: targetChatId, // 使用保存的targetChatId
mode: isDeepSearchActive ? 'research' : 'chat'
});
if (response.success) {
// 更新会话ID如果是新会话
if (response.conversationId && !targetChatId) {
const newChatId = response.conversationId;
// 只有当前聊天与目标一致时才更新全局变量
if (currentChatId === targetChatId) {
currentChatId = newChatId;
}
if (window.chatManager) {
window.chatManager.currentChatId = newChatId;
}
// 添加新会话到侧边栏
const chatTitle = message.length > 20 ? message.substring(0, 20) + '...' : message;
addChatToSidebar(newChatId, chatTitle, true);
}
// 使用addMessageToChat统一处理AI回复
await addMessageToChat(response.answer, 'ai', targetChatId);
} else {
// 使用addMessageToChat统一处理错误消息
await addMessageToChat('抱歉,获取回复时出现错误。', 'ai', targetChatId);
}
// 恢复发送状态
window.isSubmitting = false;
updateSendUI(false);
}
} catch (error) {
console.error('发送消息失败:', error);
// 使用addMessageToChat统一处理错误消息
await addMessageToChat(`抱歉,发生了错误:${error.message}`, 'ai', targetChatId);
window.isSubmitting = false;
updateSendUI(false);
}
// 重新聚焦输入框
messageInput.focus();
}
// 新增: 添加消息到指定的聊天记录
async function addMessageToChat(content, type, chatId) {
// 确保聊天容器已显示
showChatContainer();
// 使用新的聊天管理器
if (window.chatManager && chatId) {
// 只有登录用户才保存聊天记录
if (window.chatManager.getCurrentUser()) {
// 临时切换到目标聊天ID
const originalChatId = window.chatManager.currentChatId;
window.chatManager.currentChatId = chatId;
const message = window.chatManager.addMessage(content, type);
// 恢复原来的聊天ID
window.chatManager.currentChatId = originalChatId;
}
// 如果启用了在线模式,同步到服务器
if (isOnlineMode && window.ChatAPIService) {
try {
await window.ChatAPIService.addMessage(chatId, {
content,
type,
metadata: {}
});
} catch (error) {
console.error('同步消息到服务器失败:', error);
}
}
} else {
// 兼容旧的存储方式
if (chatId && chatHistoryData.has(chatId)) {
const chatHistory = chatHistoryData.get(chatId);
chatHistory.push({
content: content,
type: type,
timestamp: new Date().toISOString()
});
chatHistoryData.set(chatId, chatHistory);
}
}
// 只有当前聊天ID与目标ID一致时才更新UI不保存数据避免重复
if (chatId === currentChatId) {
await addMessageToUI(content, type);
}
}
// 新增: 只更新UI的函数不保存数据
async function addMessageToUI(content, type) {
// 确保聊天容器已显示
showChatContainer();
// 获取聊天消息容器
const chatMessages = document.getElementById('chatMessages');
if (!chatMessages) {
console.error('聊天消息容器未找到');
return;
}
const messageItem = document.createElement('div');
messageItem.className = 'message-item mb-4';
const isUser = type === 'user';
const currentTime = new Date().toLocaleTimeString('zh-CN', {
hour: '2-digit',
minute: '2-digit'
});
// 渲染内容支持Markdown
let renderedContent = content;
if (window.markdownRenderer) {
renderedContent = window.markdownRenderer.render(content);
}
if (isUser) {
messageItem.innerHTML = `
<div class="flex justify-end">
<div class="message user-message px-4 py-3">
<div class="text-sm text-gray-800 markdown-content">${renderedContent}</div>
</div>
</div>
<div class="text-xs text-gray-500 text-right mt-1">${currentTime}</div>
`;
} else {
messageItem.innerHTML = `
<div class="flex justify-start">
<div class="message ai-message px-4 py-3">
<div class="text-sm text-gray-800 markdown-content">${renderedContent}</div>
</div>
</div>
<div class="text-xs text-gray-500 mt-1">${currentTime}</div>
`;
}
chatMessages.appendChild(messageItem);
chatMessages.scrollTop = chatMessages.scrollHeight;
}
async function addMessage(content, type) {
// 确保聊天容器已显示
showChatContainer();
// 使用新的聊天管理器
if (window.chatManager && currentChatId) {
// 只有登录用户才保存聊天记录
if (window.chatManager.getCurrentUser()) {
const message = window.chatManager.addMessage(content, type);
}
// 如果启用了在线模式,同步到服务器
if (isOnlineMode && window.ChatAPIService) {
try {
await window.ChatAPIService.addMessage(currentChatId, {
content,
type,
metadata: {}
});
} catch (error) {
console.error('同步消息到服务器失败:', error);
}
}
} else {
// 兼容旧的存储方式
if (currentChatId && chatHistoryData.has(currentChatId)) {
const chatHistory = chatHistoryData.get(currentChatId);
chatHistory.push({
content: content,
type: type,
timestamp: new Date().toISOString()
});
chatHistoryData.set(currentChatId, chatHistory);
}
}
// 获取聊天消息容器
const chatMessages = document.getElementById('chatMessages');
if (!chatMessages) {
console.error('聊天消息容器未找到');
return;
}
const messageItem = document.createElement('div');
messageItem.className = 'message-item mb-4';
const isUser = type === 'user';
const currentTime = new Date().toLocaleTimeString('zh-CN', {
hour: '2-digit',
minute: '2-digit'
});
// 渲染内容支持Markdown
let renderedContent = content;
if (window.markdownRenderer) {
renderedContent = window.markdownRenderer.render(content);
}
if (isUser) {
messageItem.innerHTML = `
<div class="flex justify-end">
<div class="message user-message px-4 py-3">
<div class="text-sm text-gray-800 markdown-content">${renderedContent}</div>
</div>
</div>
<div class="text-xs text-gray-500 text-right mt-1">${currentTime}</div>
`;
} else {
messageItem.innerHTML = `
<div class="flex justify-start">
<div class="message ai-message px-4 py-3">
<div class="text-sm text-gray-800 markdown-content">${renderedContent}</div>
</div>
</div>
<div class="text-xs text-gray-500 mt-1">${currentTime}</div>
`;
}
chatMessages.appendChild(messageItem);
chatMessages.scrollTop = chatMessages.scrollHeight;
}
}
// 添加流式消息(用于实时更新)
function addStreamMessage(content, type, messageId) {
const chatMessages = document.getElementById('chatMessages');
if (!chatMessages) {
console.error('聊天消息容器未找到');
return;
}
let messageItem = document.getElementById(`message-${messageId}`);
if (!messageItem) {
// 创建新消息元素
messageItem = document.createElement('div');
messageItem.id = `message-${messageId}`;
messageItem.className = 'message-item mb-4';
chatMessages.appendChild(messageItem);
}
const currentTime = new Date().toLocaleTimeString('zh-CN', {
hour: '2-digit',
minute: '2-digit'
});
// 渲染内容支持Markdown
let renderedContent = content;
if (window.markdownRenderer) {
renderedContent = window.markdownRenderer.render(content);
}
messageItem.innerHTML = `
<div class="flex justify-start">
<div class="message ai-message px-4 py-3">
<div class="text-sm text-gray-800 markdown-content">${renderedContent}</div>
</div>
</div>
<div class="text-xs text-gray-500 mt-1">${currentTime}</div>
`;
chatMessages.scrollTop = chatMessages.scrollHeight;
}
// 更新消息内容(用于流式更新)
function updateMessageContent(messageId, content) {
const messageItem = document.getElementById(`message-${messageId}`);
if (!messageItem) return;
const contentDiv = messageItem.querySelector('.markdown-content');
if (!contentDiv) return;
// 渲染内容支持Markdown
let renderedContent = content;
if (window.markdownRenderer) {
renderedContent = window.markdownRenderer.render(content);
}
contentDiv.innerHTML = renderedContent;
// 保持滚动在底部
const chatMessages = document.getElementById('chatMessages');
if (chatMessages) {
chatMessages.scrollTop = chatMessages.scrollHeight;
}
}
/* ===== 深度检索功能 ===== */
function toggleDeepSearch() {
isDeepSearchActive = !isDeepSearchActive;
const deepSearchToggle = document.getElementById('deepSearchToggle');
if (deepSearchToggle) {
if (isDeepSearchActive) {
deepSearchToggle.classList.add('active');
deepSearchToggle.style.backgroundColor = '#dbeafe';
deepSearchToggle.style.borderColor = '#3b82f6';
deepSearchToggle.style.color = '#1d4ed8';
} else {
deepSearchToggle.classList.remove('active');
deepSearchToggle.style.backgroundColor = '';
deepSearchToggle.style.borderColor = '';
deepSearchToggle.style.color = '';
}
}
console.log('深度检索状态:', isDeepSearchActive);
}
/* ===== 用户下拉菜单 ===== */
function initUserDropdown() {
const userMenuToggle = document.getElementById('userMenuToggle');
const userDropdown = document.getElementById('userDropdown');
if (!userMenuToggle || !userDropdown) return;
userMenuToggle.addEventListener('click', function(e) {
e.stopPropagation();
console.log('用户菜单被点击');
toggleDropdown();
});
// 点击其他地方关闭下拉菜单
document.addEventListener('click', function(e) {
if (!userDropdown.contains(e.target)) {
closeDropdown();
}
});
function toggleDropdown() {
if (userDropdown.classList.contains('hidden')) {
userDropdown.classList.remove('hidden');
console.log('打开用户下拉菜单');
} else {
userDropdown.classList.add('hidden');
console.log('关闭用户下拉菜单');
}
}
function closeDropdown() {
userDropdown.classList.add('hidden');
}
}
/* ===== 下载弹窗功能 ===== */
function initDownloadModal() {
const downloadBtn = document.getElementById('downloadBtn');
const downloadAppBtn = document.getElementById('downloadAppBtn');
const downloadModal = document.getElementById('downloadModal');
const closeDownloadModal = document.getElementById('closeDownloadModal');
if (!downloadModal || !closeDownloadModal) return;
// 折叠栏下载按钮点击事件
if (downloadBtn) {
downloadBtn.addEventListener('click', function(e) {
e.preventDefault();
downloadModal.classList.remove('hidden');
});
}
// 侧边栏下载APP按钮点击事件
if (downloadAppBtn) {
downloadAppBtn.addEventListener('click', function(e) {
e.preventDefault();
downloadModal.classList.remove('hidden');
});
}
// 关闭下载弹窗
closeDownloadModal.addEventListener('click', function(e) {
e.preventDefault();
downloadModal.classList.add('hidden');
});
// 点击遮罩层关闭弹窗
downloadModal.addEventListener('click', function(e) {
if (e.target === downloadModal) {
downloadModal.classList.add('hidden');
}
});
}
/* ===== 搜索功能 ===== */
function initSearch() {
const searchInput = document.getElementById('searchInput');
if (!searchInput) return;
searchInput.addEventListener('input', function() {
const searchTerm = this.value.toLowerCase().trim();
const chatItems = document.querySelectorAll('.chat-item');
chatItems.forEach(item => {
const text = item.textContent.toLowerCase();
if (text.includes(searchTerm) || searchTerm === '') {
item.style.display = '';
} else {
item.style.display = 'none';
}
});
console.log('搜索:', searchTerm);
});
}
/* ===== 聊天历史功能 ===== */
function initChatHistoryActions() {
const chatItems = document.querySelectorAll('.chat-item');
chatItems.forEach(item => {
// 点击聊天项
item.addEventListener('click', function(e) {
if (!e.target.classList.contains('delete-chat')) {
selectChatItem(this);
console.log('选择聊天记录:', this.textContent.trim());
}
});
// 删除按钮
const deleteBtn = item.querySelector('.delete-chat');
if (deleteBtn) {
deleteBtn.addEventListener('click', function(e) {
e.stopPropagation();
deleteChatSession(item);
console.log('删除聊天记录');
});
}
});
}
function selectChatItem(item) {
// 移除其他active状态
document.querySelectorAll('.chat-history-item').forEach(chatItem => {
chatItem.classList.remove('active');
});
// 添加active状态
item.classList.add('active');
// 获取聊天ID
const chatId = item.getAttribute('data-chat-id');
// 显示聊天容器
showChatContainer();
// 加载对话内容
if (chatId) {
loadChatHistory(chatId);
console.log('加载聊天历史:', chatId);
}
}
function deleteChatSession(item) {
if (confirm('确定要删除这个对话吗?')) {
item.remove();
}
}
/* ===== 新建对话 ===== */
function startNewChat() {
// 清除active状态
document.querySelectorAll('.chat-history-item').forEach(item => {
item.classList.remove('active');
});
// 移除聊天模式类
document.body.classList.remove('chat-mode');
// 切换回欢迎模式
const chatContainer = document.getElementById('chatContainer');
const welcomeMode = document.getElementById('welcomeMode');
const chatModeInput = document.getElementById('chatModeInput');
const tickerSection = document.querySelector('.ticker-section'); // 3D新闻卡片区域
if (chatContainer) {
chatContainer.style.display = 'none';
// 恢复动画和轮播
if (window.chatModeOptimizer) {
window.chatModeOptimizer.resume();
}
}
if (welcomeMode) {
welcomeMode.style.display = 'flex'; // 使用flex保持居中布局
}
if (chatModeInput) {
chatModeInput.classList.add('hidden');
chatModeInput.style.display = 'none'; // 确保完全隐藏
}
// 显示3D新闻卡片区域
if (tickerSection) {
tickerSection.style.display = 'block';
}
// 重置当前聊天ID
currentChatId = null;
// 使用聊天管理器开始新聊天
if (window.chatManager) {
window.chatManager.startNewChat();
}
// 聚焦输入框
const messageInput = document.getElementById('messageInput');
if (messageInput) {
messageInput.focus();
}
// 如果当前正在提交消息,保持等待状态
if (window.isSubmitting) {
updateSendUI(true);
console.log('返回首页,保持等待状态');
}
console.log('开始新对话恢复欢迎界面和3D图片');
// 重新初始化文字轮播延迟执行确保DOM已更新
setTimeout(() => {
console.log('重新初始化文字轮播...');
initTextRotator();
}, 300);
}
/* ===== 辅助函数 ===== */
function showChatContainer() {
const chatContainer = document.getElementById('chatContainer');
const welcomeMode = document.getElementById('welcomeMode');
const chatModeInput = document.getElementById('chatModeInput');
const chatMessages = document.getElementById('chatMessages');
const bottomFunctionArea = document.querySelector('.flex-shrink-0'); // 底部功能区
const tickerSection = document.querySelector('.ticker-section'); // 3D新闻卡片区域
if (chatContainer && welcomeMode && chatModeInput) {
// 添加聊天模式类到body
document.body.classList.add('chat-mode');
// 隐藏欢迎模式
welcomeMode.style.display = 'none';
// 隐藏底部功能区
if (bottomFunctionArea) {
bottomFunctionArea.style.display = 'none';
}
// 隐藏3D新闻卡片区域
if (tickerSection) {
tickerSection.style.display = 'none';
console.log('showChatContainer: 隐藏3D图片');
} else {
console.log('showChatContainer: 未找到ticker-section');
}
// 显示聊天容器(全屏)
chatContainer.style.display = 'block';
// 优化聊天模式性能 - 暂停动画和轮播
if (window.chatModeOptimizer) {
window.chatModeOptimizer.pause();
}
// 确保聊天消息容器可见
if (chatMessages) {
chatMessages.classList.remove('hidden');
}
// 显示底部固定输入框
chatModeInput.classList.remove('hidden');
chatModeInput.style.display = 'block'; // 确保显示
// 如果当前正在提交消息,确保聊天模式也显示等待状态
if (window.isSubmitting) {
updateSendUI(true);
console.log('切换到聊天模式,保持等待状态');
}
console.log('切换到聊天模式隐藏欢迎区、3D图片和底部功能区输入框下沉到底部聊天窗口全屏显示');
}
}
async function createNewChatSession(firstMessage) {
// 使用后端会话管理不再创建本地会话ID
// 会话ID将在第一次发送消息后由后端返回
console.log('准备创建新会话等待后端返回会话ID');
// 清空当前会话ID让后端创建新会话
currentChatId = null;
// 如果使用本地聊天管理器(离线模式)
if (window.chatManager && !window.ChatAPIService) {
const chatId = window.chatManager.createChat(firstMessage);
const chat = window.chatManager.getChat(chatId);
const chatTitle = chat ? chat.title : '新对话';
// 添加到侧边栏
addChatToSidebar(chatId, chatTitle);
return chatId;
}
// 使用后端API时返回null会话ID将在第一次消息响应时获得
return null;
}
function addChatToSidebar(chatId, title, shouldSelect = false) {
const chatHistory = document.querySelector('.chat-history-list');
if (!chatHistory) return;
// 检查会话是否已经存在于侧边栏
const existingItem = chatHistory.querySelector(`[data-chat-id="${chatId}"]`);
if (existingItem) {
console.log(`会话 ${chatId} 已存在于侧边栏,跳过添加`);
// 如果需要选中,直接选中现有项
if (shouldSelect) {
existingItem.click();
}
return;
}
// 创建新的聊天项
const chatItem = document.createElement('div');
chatItem.className = 'chat-history-item';
chatItem.setAttribute('data-chat-id', chatId);
chatItem.innerHTML = `
<div class="chat-title">${title}</div>
<button class="delete-chat" style="display: none; position: absolute; right: 10px; top: 50%; transform: translateY(-50%); background: none; border: none; color: #999; cursor: pointer;">
<i class="fas fa-trash"></i>
</button>
`;
// 添加鼠标悬停显示删除按钮
chatItem.addEventListener('mouseenter', function() {
const deleteBtn = this.querySelector('.delete-chat');
if (deleteBtn) deleteBtn.style.display = 'block';
});
chatItem.addEventListener('mouseleave', function() {
const deleteBtn = this.querySelector('.delete-chat');
if (deleteBtn) deleteBtn.style.display = 'none';
});
// 添加事件监听器
chatItem.addEventListener('click', function(e) {
if (!e.target.classList.contains('delete-chat') && !e.target.closest('.delete-chat')) {
selectChatItem(this);
console.log('选择聊天记录:', title);
// 切换到选中的聊天
if (window.chatManager) {
const switched = window.chatManager.switchToChat(chatId);
console.log('切换聊天结果:', switched);
if (!switched) {
console.error('聊天切换失败聊天ID不存在:', chatId);
}
} else {
// 兼容旧方式
loadChatHistory(chatId);
}
}
});
const deleteBtn = chatItem.querySelector('.delete-chat');
if (deleteBtn) {
deleteBtn.addEventListener('click', function(e) {
e.stopPropagation();
// 使用新的聊天管理器删除
if (window.chatManager) {
const confirmDelete = confirm('确定要删除这个聊天记录吗?');
if (confirmDelete) {
window.chatManager.deleteChat(chatId);
console.log('删除聊天记录:', chatId);
}
} else {
// 兼容旧方式
deleteChatSession(chatItem);
console.log('删除聊天记录');
}
});
}
// 将新聊天添加到"今天"分组的第一项
const todaySection = chatHistory;
todaySection.insertBefore(chatItem, todaySection.firstChild);
// 只在需要时选中聊天(比如新创建时)
if (shouldSelect) {
selectChatItem(chatItem);
}
}
function generateAIResponse(message) {
// 根据用户输入生成包含Markdown格式的响应
const markdownResponses = [
`感谢您的提问!我正在为您分析这个问题。
## 主要观点
1. **第一点**:这是一个重要的考虑因素
2. **第二点**:需要注意相关的细节
3. **第三点**:可以从多个角度来理解
### 补充说明
> 这是一段引用,包含了一些额外的信息。
您还有其他问题吗?`,
`这是一个很有趣的话题,让我为您详细解答。
### 关键概念
- **概念A**:基础定义和说明
- **概念B**:深入理解的要点
- **概念C**:实际应用场景
\`\`\`javascript
// 示例代码
function example() {
console.log("Hello, World!");
}
\`\`\`
希望这些信息对您有所帮助!`,
`根据您的问题,我建议从以下几个方面来考虑:
1. **技术层面**
- 考虑点1
- 考虑点2
2. **实践层面**
- 实施步骤A
- 实施步骤B
### 相关资源
- [参考链接1](https://example.com)
- [参考链接2](https://example.com)
*注意*:请根据实际情况调整方案。`,
`我理解您的需求,这里有一些相关的信息可能对您有帮助。
## 解决方案
### 方案一:快速实现
\`\`\`bash
# 命令行示例
npm install package-name
npm run start
\`\`\`
### 方案二:完整配置
1. 首先,创建配置文件
2. 然后,设置必要的参数
3. 最后,运行测试验证
**提示**:记得检查兼容性问题。`,
`让我为您提供一些相关的建议和解决方案。
## 核心要点
| 特性 | 描述 | 优先级 |
|------|------|--------|
| 性能 | 优化响应速度 | 高 |
| 安全 | 加强数据保护 | 高 |
| 易用 | 改善用户体验 | 中 |
### 实施建议
> 💡 **最佳实践**:始终遵循行业标准和规范。
---
如需更多帮助,请随时告诉我!`
];
// 检查用户消息是否包含代码相关关键词
const codeKeywords = ['代码', 'code', '函数', 'function', '编程', 'programming', 'bug', '错误', 'error'];
const hasCodeContext = codeKeywords.some(keyword => message.toLowerCase().includes(keyword));
if (hasCodeContext) {
// 如果是代码相关问题,返回包含代码块的响应
return markdownResponses[1]; // 返回包含代码示例的响应
}
// 随机返回一个Markdown格式的响应
return markdownResponses[Math.floor(Math.random() * markdownResponses.length)];
}
// 删除旧的loadChatHistory函数使用后面定义的新版本
/* ===== 文字轮播技术 ===== */
function initTextRotator() {
// 文字轮播功能
class TextRotator {
constructor(options) {
this.element = document.querySelector(options.selector);
this.words = options.words || ['资料', '专家', '活动', '标准', '合作'];
this.interval = options.interval || 2500;
this.currentIndex = 0;
this.isAnimating = false;
if (this.element) {
this.init();
}
}
init() {
// 开始时显示第一个词
this.element.textContent = this.words[0];
console.log('文字轮播初始化:', this.words[0]);
// 等待一段时间后开始轮播
setTimeout(() => {
this.startRotation();
console.log('开始文字轮播');
}, 1000);
}
startRotation() {
setInterval(() => {
this.rotateText();
}, this.interval);
}
rotateText() {
if (this.isAnimating) return;
this.isAnimating = true;
const nextWord = this.words[(this.currentIndex + 1) % this.words.length];
console.log('轮播切换到:', nextWord);
// 同时获取倒影元素
const reflectionElement = document.querySelector('#rotating-word-reflection');
// 退出动画
this.element.style.transition = 'all 0.2s ease-out';
this.element.style.opacity = '0';
this.element.style.transform = 'translateY(-10px) scale(1.02)';
if (reflectionElement) {
reflectionElement.style.transition = 'all 0.2s ease-out';
reflectionElement.style.opacity = '0';
reflectionElement.style.transform = 'translateY(10px) scale(1.02)';
}
setTimeout(() => {
// 更换文字
this.currentIndex = (this.currentIndex + 1) % this.words.length;
this.element.textContent = this.words[this.currentIndex];
if (reflectionElement) {
reflectionElement.textContent = this.words[this.currentIndex];
}
console.log('文字已更换为:', this.words[this.currentIndex]);
// 重置位置准备进入动画
this.element.style.transition = 'none';
this.element.style.transform = 'translateY(10px) scale(0.98)';
this.element.style.opacity = '0';
if (reflectionElement) {
reflectionElement.style.transition = 'none';
reflectionElement.style.transform = 'translateY(-10px) scale(0.98)';
reflectionElement.style.opacity = '0';
}
// 强制重绘
requestAnimationFrame(() => {
// 进入动画
this.element.style.transition = 'all 0.3s ease-out';
this.element.style.opacity = '1';
this.element.style.transform = 'translateY(0) scale(1)';
if (reflectionElement) {
reflectionElement.style.transition = 'all 0.3s ease-out';
reflectionElement.style.opacity = '0.7';
reflectionElement.style.transform = 'translateY(0) scale(1)';
}
setTimeout(() => {
this.isAnimating = false;
console.log('动画完成');
}, 300);
});
}, 200);
}
}
// 初始化文字轮播
const rotatingElement = document.querySelector('#rotating-word');
console.log('轮播元素查找结果:', rotatingElement);
if (rotatingElement) {
const textRotator = new TextRotator({
selector: '#rotating-word',
words: ['资料', '专家', '活动', '标准', '合作'],
interval: 2500
});
// 添加点击跳转功能和波纹效果
rotatingElement.addEventListener('click', function(e) {
console.log('点击轮播文字:', this.textContent);
// 创建波纹效果
const ripple = document.createElement('div');
const rect = this.getBoundingClientRect();
const size = Math.max(rect.width, rect.height);
const x = e.clientX - rect.left - size / 2;
const y = e.clientY - rect.top - size / 2;
ripple.style.cssText = `
position: absolute;
width: ${size}px;
height: ${size}px;
left: ${x}px;
top: ${y}px;
background: radial-gradient(circle, rgba(30, 64, 175, 0.3) 0%, transparent 70%);
border-radius: 50%;
transform: scale(0);
animation: ripple 0.6s ease-out;
pointer-events: none;
z-index: 1;
`;
this.style.position = 'relative';
this.appendChild(ripple);
setTimeout(() => {
ripple.remove();
}, 600);
// 跳转到新窗口
window.open('https://yundage.com/home', '_blank');
});
// 3D鼠标跟随效果已移除保持静态显示
} else {
console.error('未找到轮播元素 #rotating-word');
}
}
/* ===== 鼠标跟随翻转卡片新闻跑马灯功能 ===== */
function init3DTicker() {
const ticker3D = document.getElementById('ticker3D');
const tickerCarousel = document.getElementById('tickerCarousel');
const tickerParticles = document.getElementById('tickerParticles');
if (!ticker3D || !tickerCarousel || !tickerParticles) {
console.log('翻转卡片跑马灯元素未找到');
return;
}
console.log('初始化鼠标跟随翻转卡片新闻跑马灯');
let newsIndex = 0;
// 新闻图片数据对应images目录下的新闻1-10.png
const newsData = [
{ image: '新闻1.png', alt: '新闻1' },
{ image: '新闻2.png', alt: '新闻2' },
{ image: '新闻3.png', alt: '新闻3' },
{ image: '新闻4.png', alt: '新闻4' },
{ image: '新闻5.png', alt: '新闻5' },
{ image: '新闻6.png', alt: '新闻6' },
{ image: '新闻7.png', alt: '新闻7' },
{ image: '新闻8.png', alt: '新闻8' },
{ image: '新闻9.png', alt: '新闻9' },
{ image: '新闻10.png', alt: '新闻10' }
];
// 创建背景粒子
function createTickerParticles() {
tickerParticles.innerHTML = '';
for (let i = 0; i < 8; i++) {
const particle = document.createElement('div');
particle.className = 'ticker-particle';
particle.style.left = Math.random() * 100 + '%';
particle.style.animationDelay = Math.random() * 8 + 's';
particle.style.animationDuration = (Math.random() * 4 + 6) + 's';
tickerParticles.appendChild(particle);
}
}
// 双向鼠标跟随翻转效果
function initMouseFollowFlip() {
const cards = tickerCarousel.querySelectorAll('.ticker-flip-card');
let lastMouseX = 0;
let lastDirection = 0; // -1左1右0静止
// 鼠标移动事件
ticker3D.addEventListener('mousemove', function(e) {
const rect = ticker3D.getBoundingClientRect();
const mouseX = e.clientX - rect.left;
// 计算鼠标移动方向
const direction = mouseX > lastMouseX ? 1 : mouseX < lastMouseX ? -1 : 0;
if (direction !== 0) {
lastDirection = direction;
}
lastMouseX = mouseX;
// 为每个卡片计算翻转角度
cards.forEach((card, index) => {
const cardRect = card.getBoundingClientRect();
const cardLeft = cardRect.left - rect.left;
const cardRight = cardLeft + cardRect.width;
const cardWidth = cardRect.width;
const cardCenter = cardLeft + cardWidth / 2;
// 计算鼠标到卡片中心的距离
const distanceToCenter = Math.abs(mouseX - cardCenter);
const maxDistance = cardWidth * 2; // 影响范围扩大到卡片宽度的2倍
// 基础翻转进度(基于鼠标在卡片中的位置)
let baseProgress = 0;
if (mouseX >= cardLeft && mouseX <= cardRight) {
// 鼠标在卡片范围内
baseProgress = (mouseX - cardLeft) / cardWidth;
} else if (mouseX < cardLeft) {
// 鼠标在卡片左侧
const distanceFromLeft = cardLeft - mouseX;
baseProgress = Math.max(0, 1 - (distanceFromLeft / cardWidth));
} else {
// 鼠标在卡片右侧
const distanceFromRight = mouseX - cardRight;
baseProgress = Math.max(0, 1 - (distanceFromRight / cardWidth));
}
// 邻近卡片的影响(双向)
let neighborInfluence = 0;
// 检查相邻卡片的影响
for (let i = 0; i < cards.length; i++) {
if (i === index) continue;
const neighborCard = cards[i];
const neighborRect = neighborCard.getBoundingClientRect();
const neighborLeft = neighborRect.left - rect.left;
const neighborRight = neighborLeft + neighborRect.width;
const neighborCenter = neighborLeft + neighborRect.width / 2;
// 如果鼠标在相邻卡片上,计算对当前卡片的影响
if (mouseX >= neighborLeft && mouseX <= neighborRight) {
const neighborProgress = (mouseX - neighborLeft) / neighborRect.width;
const distance = Math.abs(index - i);
const influence = neighborProgress * Math.pow(0.6, distance); // 距离越远影响越小
// 根据方向确定影响方式
if ((i < index && lastDirection === 1) || (i > index && lastDirection === -1)) {
neighborInfluence = Math.max(neighborInfluence, influence);
}
}
}
// 计算最终翻转进度
const finalProgress = Math.min(1, Math.max(0, baseProgress + neighborInfluence));
// 根据鼠标方向和位置决定翻转角度
let rotationAngle = 0;
if (finalProgress > 0) {
// 基础翻转角度
rotationAngle = finalProgress * 180;
// 考虑方向性:从右往左时可能需要反向翻转
if (lastDirection === -1 && mouseX < cardCenter) {
// 从右往左且鼠标在卡片左侧时,使用反向翻转
rotationAngle = (1 - finalProgress) * 180;
}
}
// 应用真正的3D翻转效果
const inner = card.querySelector('.flip-card-inner');
if (inner) {
inner.style.transform = `rotateY(${rotationAngle}deg)`;
}
// 调试信息(只显示第一张卡片)
if (index === 0) {
console.log(`Card ${index}: mouseX=${mouseX.toFixed(0)}, direction=${lastDirection}, baseProgress=${baseProgress.toFixed(2)}, neighborInfluence=${neighborInfluence.toFixed(2)}, rotation=${rotationAngle.toFixed(1)}°`);
}
});
});
// 鼠标离开时重置
ticker3D.addEventListener('mouseleave', function() {
cards.forEach(card => {
const inner = card.querySelector('.flip-card-inner');
if (inner) {
inner.style.transform = 'rotateY(0deg)';
}
});
lastMouseX = 0;
lastDirection = 0;
});
// 鼠标进入时记录初始位置
ticker3D.addEventListener('mouseenter', function(e) {
const rect = ticker3D.getBoundingClientRect();
lastMouseX = e.clientX - rect.left;
lastDirection = 0;
});
}
// 新闻轮播功能 - 更新卡片内容
function rotateNews() {
const cards = tickerCarousel.querySelectorAll('.ticker-flip-card');
cards.forEach((card, index) => {
const currentNewsIndex = (newsIndex + index) % newsData.length;
const newsItem = newsData[currentNewsIndex];
// 更新正面图片
const frontImage = card.querySelector('.flip-card-front .news-image');
if (frontImage) {
frontImage.src = `images/${newsItem.image}`;
frontImage.alt = newsItem.alt;
}
// 更新背面图片(保持一致)
const backImage = card.querySelector('.flip-card-back .news-image');
if (backImage) {
backImage.src = `images/${newsItem.image}`;
backImage.alt = newsItem.alt;
}
// 更新data属性
card.setAttribute('data-news', newsItem.alt);
card.setAttribute('data-image', newsItem.image);
});
newsIndex = (newsIndex + 1) % newsData.length;
}
// 卡片点击事件
function addCardListeners() {
const cards = tickerCarousel.querySelectorAll('.ticker-flip-card');
cards.forEach(card => {
card.addEventListener('click', function() {
const newsText = this.getAttribute('data-news');
console.log('点击新闻卡片:', newsText);
// 点击后跳转到微信文章,在新窗口中打开
window.open('https://mp.weixin.qq.com/s/QfUgaORgErymzezvSISlJQ', '_blank');
});
// 悬停时暂停轮播
card.addEventListener('mouseenter', function() {
clearInterval(newsRotationInterval);
});
// 离开时恢复轮播
card.addEventListener('mouseleave', function() {
startNewsRotation();
});
});
}
function showNewsInChat(newsText) {
const messageInput = document.getElementById('messageInput');
if (messageInput) {
const cleanText = newsText.replace(/[🔥📚👥🎯🤝🚀💡🌟]/g, '').trim();
messageInput.value = `告诉我更多关于"${cleanText}"的信息`;
messageInput.focus();
}
}
// 启动新闻轮播
let newsRotationInterval;
function startNewsRotation() {
clearInterval(newsRotationInterval);
newsRotationInterval = setInterval(rotateNews, 5000); // 每5秒轮换一次
}
// 响应式处理
function handleResize() {
createTickerParticles();
}
// 初始化
createTickerParticles();
addCardListeners();
startNewsRotation();
initMouseFollowFlip(); // 初始化鼠标跟随翻转
window.addEventListener('resize', handleResize);
console.log('鼠标跟随翻转卡片新闻跑马灯初始化完成');
}
/* ===== 聊天管理器相关功能 ===== */
function initChatManagerListeners() {
if (!window.chatManager) return;
// 监听聊天切换事件
window.addEventListener('chatManager:chatSwitched', (e) => {
const { chatId, chat } = e.detail;
console.log('切换到聊天:', chatId);
currentChatId = chatId;
loadChatHistory(chatId);
});
// 监听聊天删除事件
window.addEventListener('chatManager:chatDeleted', (e) => {
const { chatId } = e.detail;
console.log('删除聊天:', chatId);
// 从侧边栏移除
const chatItem = document.querySelector(`[data-chat-id="${chatId}"]`);
if (chatItem) {
chatItem.remove();
}
});
// 监听新聊天创建事件
window.addEventListener('chatManager:newChatStarted', () => {
console.log('新聊天事件已触发');
// 不要在这里调用 startNewChat(),避免递归
});
// 监听聊天标题更新事件
window.addEventListener('chatManager:chatTitleUpdated', (e) => {
const { chatId, title } = e.detail;
console.log('更新聊天标题:', chatId, title);
// 更新侧边栏中的标题
const chatItem = document.querySelector(`[data-chat-id="${chatId}"]`);
if (chatItem) {
const chatTitle = chatItem.querySelector('.chat-title');
if (chatTitle) {
chatTitle.textContent = title;
}
}
});
}
async function loadUserChatHistory() {
// 如果有后端API从后端加载会话列表
if (window.ChatAPIService) {
try {
const result = await window.ChatAPIService.getConversations();
if (result.success) {
// 清空现有的聊天历史显示
const chatHistoryList = document.querySelector('.chat-history-list');
if (chatHistoryList) {
chatHistoryList.innerHTML = '';
// 添加每个会话到侧边栏
result.conversations.forEach(conversation => {
// 后端返回的会话格式可能是 {id, userId, title, mode, createdAt, updatedAt}
addChatToSidebar(conversation.id, conversation.title || '新对话');
});
}
console.log(`从后端加载了 ${result.conversations.length} 个会话`);
}
} catch (error) {
console.error('加载会话列表失败:', error);
// 降级到本地存储
loadLocalChatHistory();
}
} else {
// 没有后端API使用本地存储
loadLocalChatHistory();
}
}
// 从本地存储加载聊天历史
function loadLocalChatHistory() {
if (!window.chatManager) return;
// 获取所有聊天
const chats = window.chatManager.getAllChats();
// 清空现有的聊天历史显示
const chatHistoryList = document.querySelector('.chat-history-list');
if (chatHistoryList) {
chatHistoryList.innerHTML = '';
// 添加每个聊天到侧边栏
chats.forEach(chat => {
addChatToSidebar(chat.id, chat.title);
});
}
console.log(`从本地加载了 ${chats.length} 个聊天历史`);
}
// 监听用户登录状态变化
function initUserChangeListener() {
let previousUser = localStorage.getItem('yundage_current_user');
// 监听 storage 事件(其他标签页的变化)
window.addEventListener('storage', function(e) {
if (e.key === 'yundage_current_user') {
handleUserChange(e.oldValue, e.newValue);
}
});
// 定期检查当前标签页的用户变化
setInterval(() => {
const currentUser = localStorage.getItem('yundage_current_user');
if (currentUser !== previousUser) {
handleUserChange(previousUser, currentUser);
previousUser = currentUser;
}
}, 1000);
// 监听聊天管理器的用户变化事件
window.addEventListener('chatManager:userChanged', () => {
loadUserChatHistory();
});
}
// 处理用户变化
function handleUserChange(oldUserStr, newUserStr) {
console.log('检测到用户变化');
const oldUser = oldUserStr ? JSON.parse(oldUserStr) : null;
const newUser = newUserStr ? JSON.parse(newUserStr) : null;
if (oldUser?.id !== newUser?.id) {
console.log(`用户从 ${oldUser?.username || '未登录'} 切换到 ${newUser?.username || '未登录'}`);
// 重新加载聊天记录
if (window.chatManager) {
window.chatManager.reloadForUser();
}
// 清空当前显示的聊天内容
const chatMessages = document.getElementById('chatMessages');
if (chatMessages) {
chatMessages.innerHTML = '';
}
// 切回欢迎界面
startNewChat();
}
}
// 更新loadChatHistory函数以使用新的聊天管理器
async function loadChatHistory(chatId) {
// 清空当前聊天显示
const chatMessages = document.getElementById('chatMessages');
if (chatMessages) {
chatMessages.innerHTML = '';
}
// 设置当前聊天ID
currentChatId = chatId;
// 直接使用本地存储加载消息
// 因为HippoDeepService的getConversationMessages实际上也是从本地chatManager加载的
// 避免重复加载导致消息显示两次
loadLocalChatMessages(chatId);
// 显示聊天容器
showChatContainer();
// 高亮当前聊天项
highlightActiveChatItem(chatId);
// 强制触发一次布局重新计算,确保输入框宽度正确
setTimeout(() => {
const chatModeInput = document.getElementById('chatModeInput');
if (chatModeInput) {
// 触发重新渲染
chatModeInput.style.display = 'none';
void chatModeInput.offsetHeight; // 强制重排
chatModeInput.style.display = 'block';
}
// 如果有视口处理器,也触发重新计算
if (window.viewportHandler) {
window.viewportHandler.forceRecalculate();
}
}, 50);
}
// 高亮当前活动的聊天项
function highlightActiveChatItem(chatId) {
// 移除所有聊天项的active类
document.querySelectorAll('.chat-history-item').forEach(item => {
item.classList.remove('active');
});
// 添加active类到当前聊天项
const activeItem = document.querySelector(`[data-chat-id="${chatId}"]`);
if (activeItem) {
activeItem.classList.add('active');
}
}
// 从本地存储加载聊天消息
function loadLocalChatMessages(chatId) {
// 从聊天管理器加载消息
if (window.chatManager) {
console.log(`[loadChatHistory] 从本地加载聊天: ${chatId}`);
console.log(`[loadChatHistory] 当前chatManager.currentChatId: ${window.chatManager.currentChatId}`);
// 如果不是当前聊天,才需要切换
if (window.chatManager.currentChatId !== chatId) {
console.log(`[loadChatHistory] 切换到聊天: ${chatId}`);
window.chatManager.switchToChat(chatId);
}
const chat = window.chatManager.getChat(chatId);
if (chat && chat.messages) {
const chatMessages = document.getElementById('chatMessages');
chat.messages.forEach(message => {
// 直接创建消息元素不调用addMessage以避免重复保存
const messageItem = document.createElement('div');
messageItem.className = 'message-item mb-4';
const isUser = message.type === 'user';
const messageTime = new Date(message.timestamp).toLocaleTimeString('zh-CN', {
hour: '2-digit',
minute: '2-digit'
});
// 渲染内容支持Markdown
let renderedContent = message.content;
if (window.markdownRenderer) {
renderedContent = window.markdownRenderer.render(message.content);
}
if (isUser) {
messageItem.innerHTML = `
<div class="flex justify-end">
<div class="message user-message px-4 py-3">
<div class="text-sm text-gray-800 markdown-content">${renderedContent}</div>
</div>
</div>
<div class="text-xs text-gray-500 text-right mt-1">${messageTime}</div>
`;
} else {
messageItem.innerHTML = `
<div class="flex justify-start">
<div class="message ai-message px-4 py-3">
<div class="text-sm text-gray-800 markdown-content">${renderedContent}</div>
</div>
</div>
<div class="text-xs text-gray-500 mt-1">${messageTime}</div>
`;
}
chatMessages.appendChild(messageItem);
});
// 滚动到底部
chatMessages.scrollTop = chatMessages.scrollHeight;
// 切换到聊天模式
showChatContainer();
// 强制重新计算布局,确保对齐
setTimeout(() => {
if (window.viewportHandler) {
window.viewportHandler.forceRecalculate();
}
}, 100);
} else {
// 即使没有消息也要切换到聊天模式
showChatContainer();
}
} else {
// 兼容旧的加载方式
loadChatHistoryLegacy(chatId);
}
}
// 保留旧的加载方式作为后备
function loadChatHistoryLegacy(chatId) {
// 原来的loadChatHistory实现
if (chatHistoryData.has(chatId)) {
const messages = chatHistoryData.get(chatId);
const chatMessages = document.getElementById('chatMessages');
messages.forEach(message => {
const messageItem = document.createElement('div');
messageItem.className = 'message-item mb-4';
const isUser = message.type === 'user';
const messageTime = new Date(message.timestamp).toLocaleTimeString('zh-CN', {
hour: '2-digit',
minute: '2-digit'
});
if (isUser) {
messageItem.innerHTML = `
<div class="flex justify-end">
<div class="message user-message px-4 py-3">
<p class="text-sm text-gray-800">${message.content}</p>
</div>
</div>
<div class="text-xs text-gray-500 text-right mt-1">${messageTime}</div>
`;
} else {
messageItem.innerHTML = `
<div class="flex justify-start">
<div class="message ai-message px-4 py-3">
<p class="text-sm text-gray-800">${message.content}</p>
</div>
</div>
<div class="text-xs text-gray-500 mt-1">${messageTime}</div>
`;
}
chatMessages.appendChild(messageItem);
});
chatMessages.scrollTop = chatMessages.scrollHeight;
showChatContainer();
// 强制重新计算布局,确保对齐
setTimeout(() => {
if (window.viewportHandler) {
window.viewportHandler.forceRecalculate();
}
}, 100);
}
}
// 全局暴露必要的函数
window.startNewChat = startNewChat;
window.toggleDeepSearch = toggleDeepSearch;
/* ===== Apple风格背景动画 ===== */
function initBackground() {
const gradientElement = document.getElementById('animatedGradient');
if (!gradientElement) return;
let time = 0;
const animateGradient = () => {
// 如果背景动画被暂停,延迟检查是否恢复
if (window.pauseBackgroundAnimation) {
setTimeout(() => {
requestAnimationFrame(animateGradient);
}, 1000); // 每秒检查一次
return;
}
time += 0.0056; // 减慢动画速度让过渡更平滑
// 柔和、低饱和度的冷色调,包含近白色
const colors = [
{ r: 180, g: 205, b: 215, a: 0.5 }, // 柔和蓝
{ r: 160, g: 195, b: 220, a: 0.4 }, // 柔和天蓝
{ r: 160, g: 220, b: 200, a: 0.35 }, // 柔和海蓝
{ r: 240, g: 248, b: 255, a: 0.6 }, // 爱丽丝蓝 (近白)
{ r: 210, g: 210, b: 230, a: 0.3 }, // 柔和薰衣草
{ r: 190, g: 140, b: 200, a: 0.25 } // 柔和紫
];
// 平滑的颜色插值函数
const lerpColor = (color1, color2, t) => ({
r: Math.round(color1.r + (color2.r - color1.r) * t),
g: Math.round(color1.g + (color2.g - color1.g) * t),
b: Math.round(color1.b + (color2.b - color1.b) * t),
a: color1.a + (color2.a - color1.a) * t
});
// 为每个渐变创建平滑的颜色变化
const getInterpolatedColor = (colorIndex, speed) => {
const totalColors = colors.length;
const colorPhase = (time * speed) % totalColors;
const currentIndex = Math.floor(colorPhase) % totalColors;
const nextIndex = (currentIndex + 1) % totalColors;
const t = colorPhase - Math.floor(colorPhase);
return lerpColor(colors[currentIndex], colors[nextIndex], t);
};
// 创建多个动画渐变,使用平滑的三角函数
const gradient1Size = 60 + Math.sin(time * 0.8) * 20;
const gradient2Size = 50 + Math.cos(time * 1.1) * 15;
const gradient3Size = 70 + Math.sin(time * 0.6) * 25;
const gradient4Size = 45 + Math.cos(time * 1.3) * 18;
// 更平滑的位置变化
const gradient1X = 30 + Math.sin(time * 0.3) * 25;
const gradient1Y = 40 + Math.cos(time * 0.4) * 20;
const gradient2X = 70 + Math.cos(time * 0.35) * 30;
const gradient2Y = 60 + Math.sin(time * 0.25) * 25;
const gradient3X = 20 + Math.sin(time * 0.45) * 35;
const gradient3Y = 80 + Math.cos(time * 0.2) * 30;
const gradient4X = 80 + Math.cos(time * 0.5) * 25;
const gradient4Y = 20 + Math.sin(time * 0.3) * 20;
// 使用插值后的颜色
const color1 = getInterpolatedColor(0, 0.3);
const color2 = getInterpolatedColor(1, 0.4);
const color3 = getInterpolatedColor(2, 0.2);
const color4 = getInterpolatedColor(3, 0.5);
// 添加额外的颜色点以增强流动感
const gradient5Size = 55 + Math.sin(time * 0.9) * 18;
const gradient6Size = 65 + Math.cos(time * 0.7) * 22;
const gradient5X = 50 + Math.cos(time * 0.4) * 20;
const gradient5Y = 30 + Math.sin(time * 0.5) * 15;
const gradient6X = 40 + Math.sin(time * 0.6) * 28;
const gradient6Y = 70 + Math.cos(time * 0.35) * 22;
const color5 = getInterpolatedColor(4, 0.35);
const color6 = getInterpolatedColor(5, 0.45);
const backgroundStyle = `
radial-gradient(${gradient1Size}% ${gradient1Size}% at ${gradient1X}% ${gradient1Y}%,
rgba(${color1.r}, ${color1.g}, ${color1.b}, ${color1.a}) 0%,
transparent 60%),
radial-gradient(${gradient2Size}% ${gradient2Size}% at ${gradient2X}% ${gradient2Y}%,
rgba(${color2.r}, ${color2.g}, ${color2.b}, ${color2.a}) 0%,
transparent 65%),
radial-gradient(${gradient3Size}% ${gradient3Size}% at ${gradient3X}% ${gradient3Y}%,
rgba(${color3.r}, ${color3.g}, ${color3.b}, ${color3.a}) 0%,
transparent 70%),
radial-gradient(${gradient4Size}% ${gradient4Size}% at ${gradient4X}% ${gradient4Y}%,
rgba(${color4.r}, ${color4.g}, ${color4.b}, ${color4.a}) 0%,
transparent 55%),
radial-gradient(${gradient5Size}% ${gradient5Size}% at ${gradient5X}% ${gradient5Y}%,
rgba(${color5.r}, ${color5.g}, ${color5.b}, ${color5.a}) 0%,
transparent 75%),
radial-gradient(${gradient6Size}% ${gradient6Size}% at ${gradient6X}% ${gradient6Y}%,
rgba(${color6.r}, ${color6.g}, ${color6.b}, ${color6.a}) 0%,
transparent 68%),
linear-gradient(135deg,
rgba(248, 250, 252, 0.9) 0%,
rgba(241, 245, 249, 0.8) 50%,
rgba(226, 232, 240, 0.9) 100%)
`;
gradientElement.style.background = backgroundStyle;
requestAnimationFrame(animateGradient);
};
requestAnimationFrame(animateGradient);
}
// ===== 初始化工具下拉菜单 =====
function initToolsDropdown() {
// 存储状态
let isDeepResearchEnabled = false;
let isShowThinkingEnabled = false;
// 欢迎模式的工具按钮和下拉菜单
const toolsMenuBtn = document.getElementById('toolsMenuBtn');
const toolsDropdown = document.getElementById('toolsDropdown');
const deepResearchItem = document.getElementById('deepResearchItem');
const showThinkingItem = document.getElementById('showThinkingItem');
const deepResearchStatus = document.getElementById('deepResearchStatus');
const showThinkingStatus = document.getElementById('showThinkingStatus');
// 聊天模式的工具按钮和下拉菜单
const chatModeToolsMenuBtn = document.getElementById('chatModeToolsMenuBtn');
const chatModeToolsDropdown = document.getElementById('chatModeToolsDropdown');
const chatModeDeepResearchItem = document.getElementById('chatModeDeepResearchItem');
const chatModeShowThinkingItem = document.getElementById('chatModeShowThinkingItem');
const chatModeDeepResearchStatus = document.getElementById('chatModeDeepResearchStatus');
const chatModeShowThinkingStatus = document.getElementById('chatModeShowThinkingStatus');
// 点击按钮显示/隐藏下拉菜单
if (toolsMenuBtn && toolsDropdown) {
toolsMenuBtn.addEventListener('click', function(e) {
e.preventDefault();
e.stopPropagation();
const isShowing = toolsDropdown.classList.contains('show');
if (isShowing) {
toolsDropdown.classList.remove('show');
toolsMenuBtn.classList.remove('active');
setTimeout(() => {
toolsDropdown.style.display = 'none';
}, 200);
} else {
toolsDropdown.style.display = 'block';
setTimeout(() => {
toolsDropdown.classList.add('show');
toolsMenuBtn.classList.add('active');
}, 10);
}
});
}
// 聊天模式工具按钮
if (chatModeToolsMenuBtn && chatModeToolsDropdown) {
chatModeToolsMenuBtn.addEventListener('click', function(e) {
e.stopPropagation();
const isShowing = chatModeToolsDropdown.classList.contains('show');
if (isShowing) {
chatModeToolsDropdown.classList.remove('show');
chatModeToolsMenuBtn.classList.remove('active');
setTimeout(() => {
chatModeToolsDropdown.style.display = 'none';
}, 200);
} else {
chatModeToolsDropdown.style.display = 'block';
setTimeout(() => {
chatModeToolsDropdown.classList.add('show');
chatModeToolsMenuBtn.classList.add('active');
}, 10);
}
});
}
// 点击概念感知模式
let isDeepResearchToggling = false; // 防止重复触发
function toggleDeepResearch(e) {
// 如果事件存在,阻止冒泡
if (e) {
e.stopPropagation();
e.stopImmediatePropagation();
}
// 防止重复触发
if (isDeepResearchToggling) return;
isDeepResearchToggling = true;
isDeepResearchEnabled = !isDeepResearchEnabled;
// 更新状态文字
if (deepResearchStatus) {
deepResearchStatus.textContent = isDeepResearchEnabled ? '开' : '关';
deepResearchStatus.style.color = isDeepResearchEnabled ? '#2563eb' : '#666';
}
if (chatModeDeepResearchStatus) {
chatModeDeepResearchStatus.textContent = isDeepResearchEnabled ? '开' : '关';
chatModeDeepResearchStatus.style.color = isDeepResearchEnabled ? '#2563eb' : '#666';
}
// 更新菜单项样式
if (isDeepResearchEnabled) {
if (deepResearchItem) deepResearchItem.classList.add('active');
if (chatModeDeepResearchItem) chatModeDeepResearchItem.classList.add('active');
} else {
if (deepResearchItem) deepResearchItem.classList.remove('active');
if (chatModeDeepResearchItem) chatModeDeepResearchItem.classList.remove('active');
}
// 同步更新两个开关的状态
const deepResearchToggle = document.getElementById('deepResearchToggle');
const chatModeDeepResearchToggle = document.getElementById('chatModeDeepResearchToggle');
if (deepResearchToggle && deepResearchToggle.checked !== isDeepResearchEnabled) {
deepResearchToggle.checked = isDeepResearchEnabled;
}
if (chatModeDeepResearchToggle && chatModeDeepResearchToggle.checked !== isDeepResearchEnabled) {
chatModeDeepResearchToggle.checked = isDeepResearchEnabled;
}
console.log('概念感知模式:', isDeepResearchEnabled ? '开启' : '关闭');
// 延迟重置标志
setTimeout(() => {
isDeepResearchToggling = false;
}, 100);
}
// 点击显示思考
let isShowThinkingToggling = false; // 防止重复触发
function toggleShowThinking(e) {
// 如果事件存在,阻止冒泡
if (e) {
e.stopPropagation();
e.stopImmediatePropagation();
}
// 防止重复触发
if (isShowThinkingToggling) return;
isShowThinkingToggling = true;
isShowThinkingEnabled = !isShowThinkingEnabled;
// 更新状态文字
if (showThinkingStatus) {
showThinkingStatus.textContent = isShowThinkingEnabled ? '开' : '关';
showThinkingStatus.style.color = isShowThinkingEnabled ? '#2563eb' : '#666';
}
if (chatModeShowThinkingStatus) {
chatModeShowThinkingStatus.textContent = isShowThinkingEnabled ? '开' : '关';
chatModeShowThinkingStatus.style.color = isShowThinkingEnabled ? '#2563eb' : '#666';
}
// 更新菜单项样式
if (isShowThinkingEnabled) {
if (showThinkingItem) showThinkingItem.classList.add('active');
if (chatModeShowThinkingItem) chatModeShowThinkingItem.classList.add('active');
} else {
if (showThinkingItem) showThinkingItem.classList.remove('active');
if (chatModeShowThinkingItem) chatModeShowThinkingItem.classList.remove('active');
}
console.log('显示思考:', isShowThinkingEnabled ? '开启' : '关闭');
// 延迟重置标志
setTimeout(() => {
isShowThinkingToggling = false;
}, 100);
}
// 绑定点击事件 - 只绑定到开关本身,避免重复触发
const deepResearchToggle = document.getElementById('deepResearchToggle');
const showThinkingToggle = document.getElementById('showThinkingToggle');
const chatModeDeepResearchToggle = document.getElementById('chatModeDeepResearchToggle');
const chatModeShowThinkingToggle = document.getElementById('chatModeShowThinkingToggle');
if (deepResearchToggle) {
deepResearchToggle.addEventListener('change', function(e) {
e.stopPropagation();
toggleDeepResearch();
});
}
if (showThinkingToggle) {
showThinkingToggle.addEventListener('change', function(e) {
e.stopPropagation();
toggleShowThinking();
});
}
if (chatModeDeepResearchToggle) {
chatModeDeepResearchToggle.addEventListener('change', function(e) {
e.stopPropagation();
toggleDeepResearch();
});
}
if (chatModeShowThinkingToggle) {
chatModeShowThinkingToggle.addEventListener('change', function(e) {
e.stopPropagation();
toggleShowThinking();
});
}
// 点击其他地方关闭下拉菜单
document.addEventListener('click', function(e) {
if (toolsDropdown && !toolsMenuBtn.contains(e.target) && !toolsDropdown.contains(e.target)) {
toolsDropdown.classList.remove('show');
toolsMenuBtn.classList.remove('active');
setTimeout(() => {
toolsDropdown.style.display = 'none';
}, 200);
}
if (chatModeToolsDropdown && !chatModeToolsMenuBtn.contains(e.target) && !chatModeToolsDropdown.contains(e.target)) {
chatModeToolsDropdown.classList.remove('show');
chatModeToolsMenuBtn.classList.remove('active');
setTimeout(() => {
chatModeToolsDropdown.style.display = 'none';
}, 200);
}
});
// 导出获取状态的方法
window.getToolsSettings = function() {
return {
deepResearch: isDeepResearchEnabled,
showThinking: isShowThinkingEnabled
};
};
}