/* ===== 云大阁网站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') {
// 如果正在发送中,执行停止操作
if (window.isSubmitting) {
console.log('用户按下ESC,中断请求');
// 中断请求
if (window.currentAbortController) {
window.currentAbortController.abort();
window.currentAbortController = null;
}
// 重置状态
window.isSubmitting = false;
// 更新UI
if (typeof updateSendUI === 'function') {
updateSendUI(false);
} else if (window.updateSendUI) {
window.updateSendUI(false);
}
// 显示提示
const statusText = document.querySelector('.status-text');
if (statusText) {
statusText.textContent = '已通过ESC取消请求';
setTimeout(() => {
statusText.textContent = '';
}, 3000);
}
// 添加系统提示到聊天窗口
const chatMessages = document.getElementById('chatMessages');
if (chatMessages) {
const cancelMsg = document.createElement('div');
cancelMsg.className = 'message-item mb-4';
cancelMsg.innerHTML = `
⚠️ 已通过ESC键取消请求。注意:后端可能仍在处理,建议稍等片刻再发送新请求。
`;
chatMessages.appendChild(cancelMsg);
// 5秒后自动移除提示
setTimeout(() => {
if (cancelMsg.parentNode) {
cancelMsg.remove();
}
}, 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;
}
});
});
}
/* ===== 聊天功能相关全局函数 ===== */
// 更新发送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');
// 聊天模式元素
const chatModeSendIcon = document.getElementById('chatModeSendIcon');
const chatModeLoadingSpinner = document.getElementById('chatModeLoadingSpinner');
const chatModeMessageInput = document.getElementById('chatModeMessageInput');
const chatModeSendBtn = document.getElementById('chatModeSendBtn');
if (isLoading) {
// 强制隐藏loading spinner
if (loadingSpinner) {
loadingSpinner.style.setProperty('display', 'none', 'important');
loadingSpinner.style.visibility = 'hidden';
}
// 显示停止图标
if (sendIcon) {
sendIcon.style.display = 'block';
sendIcon.style.visibility = 'visible';
// 将SVG图标改为停止图标(红色正方形)
sendIcon.innerHTML = '';
sendIcon.style.color = '#dc3545';
// 确保按钮可点击
if (sendBtn) {
sendBtn.style.cursor = 'pointer';
sendBtn.disabled = false; // 确保按钮不被禁用
}
}
if (statusText) statusText.textContent = 'AI is thinking...';
if (messageInput) messageInput.disabled = true;
// 更新聊天模式UI - 同样显示停止图标
if (chatModeLoadingSpinner) {
chatModeLoadingSpinner.style.setProperty('display', 'none', 'important');
chatModeLoadingSpinner.style.visibility = 'hidden';
}
if (chatModeSendIcon) {
chatModeSendIcon.style.display = 'block';
chatModeSendIcon.style.visibility = 'visible';
// 对于SVG元素,设置停止图标(红色方块)
chatModeSendIcon.innerHTML = '';
chatModeSendIcon.style.color = '#dc3545';
// 确保SVG的fill属性生效
chatModeSendIcon.setAttribute('fill', '#dc3545');
chatModeSendIcon.setAttribute('stroke', 'none');
}
if (chatModeSendBtn) {
chatModeSendBtn.style.cursor = 'pointer';
chatModeSendBtn.disabled = false; // 确保按钮可点击以便停止
}
if (chatModeMessageInput) chatModeMessageInput.disabled = true;
} else {
// 恢复发送图标
if (sendIcon) {
sendIcon.style.display = 'block';
// 恢复原始的SVG发送图标
sendIcon.innerHTML = '';
sendIcon.style.color = '#999';
}
if (loadingSpinner) {
loadingSpinner.style.setProperty('display', 'none', 'important');
}
if (statusText) statusText.textContent = 'Ready to submit!';
if (messageInput) messageInput.disabled = false;
// 更新发送按钮状态
const hasText = messageInput && messageInput.value.trim().length > 0;
if (sendIcon) {
sendIcon.style.opacity = hasText && !window.isSubmitting ? '1' : '0.3';
}
// 更新聊天模式UI - 恢复发送图标
if (chatModeLoadingSpinner) {
chatModeLoadingSpinner.style.setProperty('display', 'none', 'important');
}
if (chatModeSendIcon) {
chatModeSendIcon.style.display = 'block';
// 恢复原始的发送图标
chatModeSendIcon.innerHTML = '';
chatModeSendIcon.style.color = '#999';
// 恢复SVG的默认属性
chatModeSendIcon.setAttribute('fill', 'none');
chatModeSendIcon.setAttribute('stroke', 'currentColor');
}
if (chatModeSendBtn) {
chatModeSendBtn.style.cursor = 'pointer';
}
if (chatModeMessageInput) chatModeMessageInput.disabled = false;
// 更新聊天模式按钮状态
const chatHasText = chatModeMessageInput && chatModeMessageInput.value.trim().length > 0;
if (chatModeSendIcon) {
chatModeSendIcon.style.opacity = chatHasText && !window.isSubmitting ? '1' : '0.3';
}
}
}
// 将updateSendUI暴露到全局
window.updateSendUI = updateSendUI;
/* ===== 聊天功能 ===== */
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();
e.stopPropagation();
console.log('发送按钮被点击,当前状态:', window.isSubmitting);
// 如果正在发送中,执行停止操作
if (window.isSubmitting) {
console.log('正在发送中,尝试停止...');
// 中断请求
if (window.currentAbortController) {
console.log('找到AbortController,执行中断');
window.currentAbortController.abort();
window.currentAbortController = null;
}
// 更新状态显示为已取消
if (window.currentStatusDisplay) {
window.currentStatusDisplay.updateStatus({ type: 'cancelled' });
// 清除引用
window.currentStatusDisplay = null;
}
// 重置状态
window.isSubmitting = false;
updateSendUI(false);
// 显示提示
const statusText = document.querySelector('.status-text');
if (statusText) {
statusText.textContent = '已取消请求';
setTimeout(() => {
statusText.textContent = '';
}, 3000);
}
// 添加系统提示到聊天窗口
const chatMessages = document.getElementById('chatMessages');
if (chatMessages) {
const cancelMsg = document.createElement('div');
cancelMsg.className = 'message-item mb-4';
cancelMsg.innerHTML = `
⚠️ 请求已取消。注意:后端可能仍在处理,建议稍等片刻再发送新请求。
`;
chatMessages.appendChild(cancelMsg);
// 5秒后自动移除提示
setTimeout(() => {
if (cancelMsg.parentNode) {
cancelMsg.remove();
}
}, 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();
e.stopPropagation();
console.log('聊天模式发送按钮被点击,当前状态:', window.isSubmitting);
// 如果正在发送中,执行停止操作
if (window.isSubmitting) {
console.log('聊天模式:正在发送中,尝试停止...');
// 中断请求
if (window.currentAbortController) {
console.log('聊天模式:找到AbortController,执行中断');
window.currentAbortController.abort();
window.currentAbortController = null;
}
// 更新状态显示为已取消
if (window.currentStatusDisplay) {
window.currentStatusDisplay.updateStatus({ type: 'cancelled' });
// 清除引用
window.currentStatusDisplay = null;
}
// 重置状态
window.isSubmitting = false;
updateSendUI(false);
// 添加系统提示到聊天窗口
const chatMessages = document.getElementById('chatMessages');
if (chatMessages) {
const cancelMsg = document.createElement('div');
cancelMsg.className = 'message-item mb-4';
cancelMsg.innerHTML = `
⚠️ 请求已取消。注意:后端可能仍在处理,建议稍等片刻再发送新请求。
`;
chatMessages.appendChild(cancelMsg);
// 5秒后自动移除提示
setTimeout(() => {
if (cancelMsg.parentNode) {
cancelMsg.remove();
}
}, 5000);
}
} 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';
}
}
// 聊天模式按钮状态管理
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);
// 保存到全局,以便停止时可以更新状态
window.currentStatusDisplay = statusDisplay;
}
// 保存AbortController到全局,以便中断
window.currentAbortController = window.ChatAPIService.sendMessageStream(
{
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 = `
🤔 思考过程:
`;
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);
}
// 自动调整输入框高度(参考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);
// 保存到全局,以便停止时可以更新状态
window.currentStatusDisplay = statusDisplay;
}
// 保存AbortController到全局,以便中断
window.currentAbortController = window.ChatAPIService.sendMessageStream(
{
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);
// 清除状态显示引用
window.currentStatusDisplay = null;
},
// onError: 错误回调
(error) => {
console.error('流式响应错误:', error);
addMessage(`抱歉,发生了错误:${error.message}`, 'ai');
window.isSubmitting = false;
updateSendUI(false);
// 清除状态显示引用
window.currentStatusDisplay = null;
},
// 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 = `
🤔 思考过程:
`;
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 = `
${currentTime}
`;
} else {
messageItem.innerHTML = `
${currentTime}
`;
}
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 = `
${currentTime}
`;
} else {
messageItem.innerHTML = `
${currentTime}
`;
}
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 = `
${currentTime}
`;
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';
}
// 如果当前正在等待中,保持等待状态
if (window.isSubmitting) {
// 确保首页也显示等待状态
updateSendUI(true);
console.log('返回首页,保持等待状态');
}
// 重置当前聊天ID
currentChatId = null;
// 使用聊天管理器开始新聊天
if (window.chatManager) {
window.chatManager.startNewChat();
}
// 聚焦输入框
const messageInput = document.getElementById('messageInput');
if (messageInput) {
messageInput.focus();
}
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函数来同步两个界面的状态
updateSendUI(true);
}
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 = `
${title}
`;
// 添加鼠标悬停显示删除按钮
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 = `
${messageTime}
`;
} else {
messageItem.innerHTML = `
${messageTime}
`;
}
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 = `
${messageTime}
`;
} else {
messageItem.innerHTML = `
${messageTime}
`;
}
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
};
};
}