(function () { if (document.getElementById('ai-assistant-styles')) return; var style = document.createElement('style'); style.id = 'ai-assistant-styles'; style.textContent = '\ .ai-assistant-btn {\ position: fixed; bottom: 24px; right: 24px;\ z-index: 99999;\ width: 52px; height: 52px;\ border-radius: 50%;\ background: linear-gradient(135deg, #2563eb, #1d4ed8);\ color: #fff;\ border: none;\ cursor: pointer;\ box-shadow: 0 4px 16px rgba(37,99,235,0.35);\ display: flex; align-items: center; justify-content: center;\ font-size: 22px;\ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\ }\ .ai-assistant-btn:hover { transform: scale(1.1); box-shadow: 0 6px 24px rgba(37,99,235,0.45); }\ .ai-assistant-btn.open { transform: rotate(45deg); background: #f56c6c; box-shadow: 0 4px 16px rgba(245,108,108,0.35); }\ .ai-assistant-panel {\ position: fixed; bottom: 88px; right: 24px;\ z-index: 99998;\ width: 380px; height: 560px;\ background: #fff;\ border-radius: 16px;\ box-shadow: 0 8px 40px rgba(0,0,0,0.15);\ display: none;\ flex-direction: column;\ overflow: hidden;\ animation: aiSlideUp 0.3s ease-out;\ border: 1px solid #e5e7eb;\ }\ .ai-assistant-panel.open { display: flex; }\ @keyframes aiSlideUp {\ from { opacity: 0; transform: translateY(20px) scale(0.95); }\ to { opacity: 1; transform: translateY(0) scale(1); }\ }\ .ai-assistant-header {\ padding: 14px 16px;\ background: linear-gradient(135deg, #2563eb, #1d4ed8);\ color: #fff;\ font-weight: 600;\ font-size: 15px;\ display: flex; align-items: center; gap: 8px;\ flex-shrink: 0;\ }\ .ai-assistant-header .ai-badge {\ background: rgba(255,255,255,0.2);\ padding: 2px 8px; border-radius: 10px;\ font-size: 10px; font-weight: 400;\ }\ .ai-assistant-messages {\ flex: 1; overflow-y: auto;\ padding: 12px 16px;\ background: #f8f9fb;\ display: flex; flex-direction: column; gap: 10px;\ }\ .ai-assistant-msg {\ max-width: 85%;\ padding: 10px 14px;\ border-radius: 12px;\ font-size: 13px;\ line-height: 1.6;\ word-break: break-word;\ white-space: pre-wrap;\ }\ .ai-assistant-msg.ai {\ background: #fff;\ border: 1px solid #e5e7eb;\ color: #303133;\ align-self: flex-start;\ border-bottom-left-radius: 4px;\ }\ .ai-assistant-msg.user {\ background: #2563eb;\ color: #fff;\ align-self: flex-end;\ border-bottom-right-radius: 4px;\ }\ .ai-assistant-msg .msg-time {\ font-size: 10px; opacity: 0.6;\ margin-top: 4px; display: block;\ }\ .ai-assistant-typing {\ align-self: flex-start;\ display: flex; gap: 4px;\ padding: 12px 16px;\ background: #fff;\ border: 1px solid #e5e7eb;\ border-radius: 12px;\ border-bottom-left-radius: 4px;\ }\ .ai-assistant-typing span {\ width: 6px; height: 6px;\ background: #909399;\ border-radius: 50%;\ animation: aiBounce 1.4s ease-in-out infinite;\ }\ .ai-assistant-typing span:nth-child(2) { animation-delay: 0.2s; }\ .ai-assistant-typing span:nth-child(3) { animation-delay: 0.4s; }\ @keyframes aiBounce {\ 0%, 60%, 100% { transform: translateY(0); }\ 30% { transform: translateY(-6px); }\ }\ .ai-assistant-input {\ display: flex; align-items: center;\ padding: 10px 12px;\ border-top: 1px solid #e5e7eb;\ background: #fff;\ flex-shrink: 0;\ gap: 8px;\ }\ .ai-assistant-input textarea {\ flex: 1;\ border: 1px solid #d1d5db;\ border-radius: 8px;\ padding: 8px 12px;\ font-size: 13px;\ outline: none;\ resize: none;\ height: 36px;\ line-height: 20px;\ font-family: inherit;\ transition: border-color 0.2s;\ }\ .ai-assistant-input textarea:focus { border-color: #2563eb; }\ .ai-assistant-send {\ width: 36px; height: 36px;\ border-radius: 8px;\ background: #2563eb;\ color: #fff;\ border: none;\ cursor: pointer;\ font-size: 16px;\ display: flex; align-items: center; justify-content: center;\ transition: all 0.2s;\ flex-shrink: 0;\ }\ .ai-assistant-send:hover { background: #1d4ed8; }\ .ai-assistant-send:disabled { background: #c0c4cc; cursor: not-allowed; }\ .ai-assistant-greeting {\ text-align: center;\ padding: 20px 16px;\ color: #909399;\ font-size: 13px;\ }\ .ai-assistant-greeting .greeting-icon {\ font-size: 36px; margin-bottom: 8px;\ }\ .ai-assistant-greeting h4 {\ color: #303133; font-size: 15px;\ margin: 0 0 6px;\ }\ @media (max-width: 480px) {\ .ai-assistant-panel {\ right: 12px; left: 12px;\ width: auto;\ height: 480px;\ bottom: 80px;\ }\ .ai-assistant-btn { right: 16px; bottom: 16px; }\ }\ '; document.head.appendChild(style); var token = localStorage.getItem('authToken'); if (!token) return; var pageMap = { '/': 'dashboard', '/index.html': 'dashboard', 'topics.html': 'topics', 'metrics.html': 'metrics', 'calendar.html': 'calendar', 'assets.html': 'assets', 'tasks.html': 'tasks', 'platforms.html': 'platforms', 'admin.html': 'admin', 'factory.html': 'factory', 'insights.html': 'insights' }; var path = window.location.pathname; var currentPage = pageMap[path] || pageMap['/']; var greettings = { 'dashboard': '👋 欢迎回来!我可以帮你了解仪表盘上的统计数据、模块状态的含义,或指导你如何快速定位待处理选题。', 'topics': '📝 这里是选题管理。我可以帮你了解如何创建选题、设置评分、编辑内容,或如何使用预览功能查看各平台文章效果。', 'metrics': '📊 数据分析页展示内容表现。我可以帮你解读图表数据、分析各平台效果差异,或建议如何提升内容互动率。', 'calendar': '📅 内容日历帮你规划发布节奏。我可以教你如何创建计划、调整日期,或优化内容排期策略。', 'assets': '🖼️ 素材库管理图片和文件。我可以指导你如何上传素材、添加标签分类,或关联到相关选题。', 'tasks': '⚡ 任务页面跟踪所有创作任务。我可以解释各任务的含义、查看执行进度,或排查任务失败原因。', 'platforms': '🔗 平台配置管理各发布渠道。我可以帮你了解如何配置平台参数、设置发布格式。', 'admin': '⚙️ 系统管理页面。我可以帮你管理用户、配置 LLM、查看运行日志,或设置采集类别和信息源。', 'factory': '🏭 这里是内容工厂。我可以帮你了解创作流程,从选题到发布的全链路跟踪,或排查任务失败原因。', 'insights': '📈 数据洞察页面。我可以帮你解读内容表现数据、搜索排名变化趋势,或建议如何提升 GEO 就绪度。', }; var HISTORY_KEY = 'ai_assistant_history_' + currentPage; var saved = []; try { saved = JSON.parse(localStorage.getItem(HISTORY_KEY)) || []; } catch(e) {} var container = document.createElement('div'); container.innerHTML = '\ \
\
\ 🤖 AI 助手\ ' + currentPage + '\
\
\
\
\ \ \
\
\ '; document.body.appendChild(container); var btn = document.getElementById('aiAssistantBtn'); var panel = document.getElementById('aiAssistantPanel'); var messagesEl = document.getElementById('aiMessages'); var input = document.getElementById('aiInput'); var sendBtn = document.getElementById('aiSendBtn'); function addMessage(role, content) { var div = document.createElement('div'); div.className = 'ai-assistant-msg ' + role; div.textContent = content; messagesEl.appendChild(div); messagesEl.scrollTop = messagesEl.scrollHeight; } function showGreeting() { messagesEl.innerHTML = '\
\
🤖
\

宇之然 AI 助手

\

' + (greettings[currentPage] || '👋 你好!有什么可以帮助你的?') + '

\
'; } function showTyping() { var div = document.createElement('div'); div.className = 'ai-assistant-typing'; div.id = 'aiTyping'; div.innerHTML = ''; messagesEl.appendChild(div); messagesEl.scrollTop = messagesEl.scrollHeight; } function removeTyping() { var t = document.getElementById('aiTyping'); if (t) t.remove(); } function saveHistory(history) { try { localStorage.setItem(HISTORY_KEY, JSON.stringify(history.slice(-50))); } catch(e) {} } async function sendMessage(text) { if (!text.trim()) return; input.value = ''; input.style.height = '36px'; addMessage('user', text); if (messagesEl.querySelector('.ai-assistant-greeting')) { messagesEl.querySelector('.ai-assistant-greeting').remove(); } sendBtn.disabled = true; var history = []; var msgs = messagesEl.querySelectorAll('.ai-assistant-msg'); msgs.forEach(function(m) { history.push({ role: m.classList.contains('user') ? 'user' : 'assistant', content: m.textContent }); }); showTyping(); try { var resp = await fetch('/api/assistant/chat', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + token }, var currentUser = null; try { currentUser = JSON.parse(localStorage.getItem('currentUser')); } catch(e) {} body: JSON.stringify({ message: text, page: currentPage, history: history, org_id: currentUser?.org_id || 'default' }) }); removeTyping(); if (resp.ok) { var data = await resp.json(); addMessage('assistant', data.reply || '已收到'); saveHistory(history.concat([ { role: 'user', content: text }, { role: 'assistant', content: data.reply || '已收到' } ])); } else { addMessage('assistant', '抱歉,请求失败,请稍后重试。'); } } catch(e) { removeTyping(); addMessage('assistant', '网络异常,请检查连接后重试。'); } sendBtn.disabled = false; input.focus(); } // Open/close var isOpen = false; btn.addEventListener('click', function() { isOpen = !isOpen; btn.classList.toggle('open', isOpen); panel.classList.toggle('open', isOpen); if (isOpen) { var msgs = messagesEl.querySelectorAll('.ai-assistant-msg'); if (msgs.length === 0) { // Load saved or show greeting if (saved.length > 0) { saved.forEach(function(m) { addMessage(m.role, m.content); }); } else { showGreeting(); } } input.focus(); } }); // Send on click sendBtn.addEventListener('click', function() { sendMessage(input.value); }); // Send on Enter (Shift+Enter for newline) input.addEventListener('keydown', function(e) { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); sendMessage(input.value); } }); // Auto-resize textarea input.addEventListener('input', function() { this.style.height = '36px'; this.style.height = Math.min(this.scrollHeight, 120) + 'px'; }); // Close on Escape document.addEventListener('keydown', function(e) { if (e.key === 'Escape' && isOpen) { isOpen = false; btn.classList.remove('open'); panel.classList.remove('open'); } }); window.aiAssistantOpen = function() { btn.click(); }; window.aiAssistantClose = function() { if (isOpen) btn.click(); }; })();