// AI助手 - 后台管理前端 const API_BASE = ''; let currentPage = 'stats'; let llmConfigs = []; let agents = []; let toolConfigs = []; let chatConfigs = []; let systemConfigs = {}; // ==================== 登录 ==================== document.getElementById('loginBtn').addEventListener('click', async () => { const username = document.getElementById('loginUsername').value.trim(); const password = document.getElementById('loginPassword').value; if (!username || !password) { showToast('请输入用户名和密码'); return; } try { const res = await fetch(`${API_BASE}/api/admin/login`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username, password }) }); const data = await res.json(); if (data.success) { localStorage.setItem('adminLoggedIn', 'true'); localStorage.setItem('adminUsername', username); document.getElementById('loginPage').style.display = 'none'; document.getElementById('adminPage').style.display = 'block'; document.getElementById('adminName').textContent = username; loadPage('stats'); } else { showToast(data.error || '登录失败'); } } catch (e) { showToast('登录失败,请检查网络'); } }); // 检查登录状态 if (localStorage.getItem('adminLoggedIn') === 'true') { document.getElementById('loginPage').style.display = 'none'; document.getElementById('adminPage').style.display = 'block'; document.getElementById('adminName').textContent = localStorage.getItem('adminUsername'); loadPage('stats'); } // 退出登录 document.getElementById('logoutBtn').addEventListener('click', () => { localStorage.removeItem('adminLoggedIn'); localStorage.removeItem('adminUsername'); document.getElementById('adminPage').style.display = 'none'; document.getElementById('loginPage').style.display = 'flex'; }); // ==================== 侧边栏导航 ==================== document.querySelectorAll('.sidebar-item').forEach(item => { item.addEventListener('click', () => { const page = item.getAttribute('data-page'); document.querySelectorAll('.sidebar-item').forEach(i => i.classList.remove('active')); item.classList.add('active'); loadPage(page); }); }); // ==================== 页面加载 ==================== async function loadPage(page) { currentPage = page; const content = document.getElementById('mainContent'); switch (page) { case 'stats': await loadStatsPage(content); break; case 'users': await loadUsersPage(content); break; case 'llm': await loadLLMPage(content); break; case 'agents': await loadAgentsPage(content); break; case 'chat': await loadChatConfigPage(content); break; case 'tools': await loadToolsPage(content); break; case 'system': await loadSystemPage(content); break; } } // ==================== 统计页面 ==================== async function loadStatsPage(content) { const stats = await fetchAPI('/api/admin/stats'); content.innerHTML = `

统计信息

🧠
${stats.llm_total_calls || 0}
LLM 总调用
📊
${stats.llm_today_calls || 0}
今日 LLM 调用
🔍
${stats.search_total_calls || 0}
搜索总调用
📈
${stats.search_today_calls || 0}
今日搜索
🤖
${stats.agent_count || 0}
智能体数量
🧠
${stats.llm_count || 0}
LLM 配置数量
👥
${stats.total_users || 0}
注册用户数
📅
${new Date().toLocaleDateString()}
统计日期

热门智能体使用排行

${stats.agent_usage?.map(a => ` `).join('') || ''}
智能体 使用次数
${a.log_key} ${a.count}
暂无数据
`; } // ==================== 用户管理页面 ==================== let users = []; async function loadUsersPage(content) { users = await fetchAPI('/api/admin/users'); content.innerHTML = `

用户管理

👥
${users.length}
总用户数
🆕
${users.filter(u => { const today = new Date().toISOString().slice(0, 10); return u.created_at && u.created_at.startsWith(today); }).length}
今日新增
📧
${users.filter(u => u.email).length}
已绑定邮箱
📱
${users.length}
已绑定手机
${users.length === 0 ? '' : users.map(u => ` `).join('') }
ID 头像 用户名 手机号 邮箱 注册时间 最后登录 操作
暂无用户
${u.id} ${u.avatar || '👤'} ${u.username} ${u.phone} ${u.email || '-'} ${formatDate(u.created_at)} ${u.last_login_at ? formatDate(u.last_login_at) : '从未登录'}
`; } function formatDate(dateStr) { if (!dateStr) return '-'; const d = new Date(dateStr); return d.toLocaleDateString() + ' ' + d.toLocaleTimeString().slice(0, 5); } async function searchUsers(event) { if (event && event.key !== 'Enter') return; const search = document.getElementById('userSearch').value.trim(); users = await fetchAPI(`/api/admin/users?search=${encodeURIComponent(search)}`); loadUsersPage(document.getElementById('mainContent')); } async function searchUsersBtn() { const search = document.getElementById('userSearch').value.trim(); users = await fetchAPI(`/api/admin/users?search=${encodeURIComponent(search)}`); loadUsersPage(document.getElementById('mainContent')); } function showEditUserModal(id) { const user = users.find(u => u.id === id); if (!user) return; const avatars = ['👤', '😊', '😎', '🤓', '🦸', '🧙', '🥷', '👨', '👩', '🧑', '👴', '👵', '👦', '👧', '🤖', '👽', '🧛', '🧜', '🧚', '🦊']; showModal('编辑用户', `
`); } async function updateUser(id) { const data = { username: document.getElementById('editUserName').value, email: document.getElementById('editUserEmail').value, avatar: document.getElementById('editUserAvatar').value, signature: document.getElementById('editUserSignature').value, gender: document.getElementById('editUserGender').value, age: document.getElementById('editUserAge').value ? parseInt(document.getElementById('editUserAge').value) : null, region: document.getElementById('editUserRegion').value }; if (!data.username) { showToast('用户名不能为空'); return; } await fetchAPI(`/api/admin/users/${id}`, 'PUT', data); closeModal(); showToast('更新成功'); loadPage('users'); } function showResetPasswordModal(id) { const user = users.find(u => u.id === id); if (!user) return; showModal('重置密码', `

用户: ${user.username}

手机: ${user.phone}

⚠️ 重置后用户需使用新密码登录

`); } async function resetPassword(id) { const password = document.getElementById('resetPassword').value; if (!password || password.length < 6) { showToast('密码长度至少6位'); return; } await fetchAPI(`/api/admin/users/${id}/password`, 'PUT', { password }); closeModal(); showToast('密码已重置'); } async function deleteUser(id) { const user = users.find(u => u.id === id); if (!user) return; if (!confirm(`确定删除用户 "${user.username}"?\n此操作不可恢复!`)) return; await fetchAPI(`/api/admin/users/${id}`, 'DELETE'); showToast('删除成功'); loadPage('users'); } // ==================== 大模型配置页面 ==================== async function loadLLMPage(content) { llmConfigs = await fetchAPI('/api/admin/llm'); content.innerHTML = `

大模型配置

${llmConfigs.map(c => ` `).join('')}
名称 提供商 模型 思考模式 视觉能力 API URL 操作
${c.name} ${c.is_default ? '默认' : ''} ${c.provider} ${c.model} ${c.enable_thinking ? '✅ 支持' : '❌ 不支持'} ${c.enable_vision ? '✅ 支持' : '❌ 不支持'} ${c.api_url}
${!c.is_default ? `` : ''}
`; } function showAddLLMModal() { showModal('添加大模型配置', `
模型是否支持原生思考功能(如DeepSeek的think标签)
模型是否支持图片输入和分析
`); } function showEditLLMModal(id) { const config = llmConfigs.find(c => c.id === id); if (!config) return; showModal('编辑大模型配置', `
模型是否支持原生思考功能(如DeepSeek的think标签)
模型是否支持图片输入和分析
`); } async function saveLLM() { const data = { name: document.getElementById('llmName').value, provider: document.getElementById('llmProvider').value, api_url: document.getElementById('llmApiUrl').value, api_key: document.getElementById('llmApiKey').value, model: document.getElementById('llmModel').value, max_tokens: parseInt(document.getElementById('llmMaxTokens').value), temperature: parseFloat(document.getElementById('llmTemperature').value), enable_thinking: document.getElementById('llmEnableThinking').checked ? 1 : 0, enable_vision: document.getElementById('llmEnableVision').checked ? 1 : 0 }; if (!data.name || !data.api_url || !data.api_key || !data.model) { showToast('请填写完整信息'); return; } await fetchAPI('/api/admin/llm', 'POST', data); closeModal(); showToast('添加成功'); loadPage('llm'); } async function updateLLM(id) { const data = { name: document.getElementById('llmName').value, provider: document.getElementById('llmProvider').value, api_url: document.getElementById('llmApiUrl').value, api_key: document.getElementById('llmApiKey').value, model: document.getElementById('llmModel').value, max_tokens: parseInt(document.getElementById('llmMaxTokens').value), temperature: parseFloat(document.getElementById('llmTemperature').value), enable_thinking: document.getElementById('llmEnableThinking').checked ? 1 : 0, enable_vision: document.getElementById('llmEnableVision').checked ? 1 : 0 }; await fetchAPI(`/api/admin/llm/${id}`, 'PUT', data); closeModal(); showToast('更新成功'); loadPage('llm'); } async function setDefaultLLM(id) { await fetchAPI(`/api/admin/llm/${id}/default`, 'POST'); showToast('已设为默认'); loadPage('llm'); } async function deleteLLM(id) { if (!confirm('确定删除此配置?')) return; await fetchAPI(`/api/admin/llm/${id}`, 'DELETE'); showToast('删除成功'); loadPage('llm'); } // ==================== 智能体管理页面 ==================== async function loadAgentsPage(content) { agents = await fetchAPI('/api/admin/agents'); llmConfigs = await fetchAPI('/api/admin/llm'); toolConfigs = await fetchAPI('/api/admin/tools'); const categories = { basic: '基础', work: '工作', study: '学习', life: '生活' }; const tagLabels = { 'hot': '🔥 热门', 'popular': '👍 推荐', 'new': '🆕 新品', '': '' }; content.innerHTML = `

智能体管理

${agents.map(a => ` `).join('')}
头像 名称 类别 标签 热度 上线状态 操作
${a.avatar} ${a.name} ${categories[a.category] || a.category} ${a.tags ? a.tags.split(',').map(t => tagLabels[t] || t).filter(t => t).join(' ') : '-'} ${a.heat || 0} ${a.is_online ? '✅ 已上线' : '❌ 未上线'}

说明

上线状态

点击可快速切换,未上线则APP不可见

标签

hot=热门, popular=推荐, new=新品

类别

basic/work/study/life

`; } async function toggleAgentOnline(agentId, currentStatus) { const newStatus = currentStatus ? 0 : 1; await fetchAPI(`/api/admin/agents/${agentId}/online`, 'POST', { is_online: newStatus }); showToast(newStatus ? '已上线' : '已下线'); loadPage('agents'); } function showAddAgentModal() { showModal('添加智能体', `
可选: hot(热门), popular(推荐), new(新品)
已配置工具: ${toolConfigs.map(t => t.tool_id).join(', ')}
`); } function showEditAgentModal(agentId) { const agent = agents.find(a => a.agent_id === agentId); if (!agent) return; showModal('编辑智能体', `
可选: hot(热门), popular(推荐), new(新品)
已配置工具: ${toolConfigs.map(t => t.tool_id).join(', ')}
`); } async function saveAgent() { const data = { agent_id: document.getElementById('agentId').value, name: document.getElementById('agentName').value, avatar: document.getElementById('agentAvatar').value, category: document.getElementById('agentCategory').value, tags: document.getElementById('agentTags').value, description: document.getElementById('agentDescription').value, system_prompt: document.getElementById('agentPrompt').value, llm_config_id: document.getElementById('agentLLM').value || null, enable_tools: document.getElementById('agentEnableTools').value, heat: parseInt(document.getElementById('agentHeat').value), is_online: document.getElementById('agentIsOnline').checked ? 1 : 0 }; if (!data.agent_id || !data.name || !data.system_prompt) { showToast('请填写完整信息'); return; } await fetchAPI('/api/admin/agents', 'POST', data); closeModal(); showToast('添加成功'); loadPage('agents'); } async function updateAgent(agentId) { const data = { name: document.getElementById('agentName').value, avatar: document.getElementById('agentAvatar').value, category: document.getElementById('agentCategory').value, tags: document.getElementById('agentTags').value, description: document.getElementById('agentDescription').value, system_prompt: document.getElementById('agentPrompt').value, llm_config_id: document.getElementById('agentLLM').value || null, enable_tools: document.getElementById('agentEnableTools').value, heat: parseInt(document.getElementById('agentHeat').value), is_online: document.getElementById('agentIsOnline').checked ? 1 : 0 }; await fetchAPI(`/api/admin/agents/${agentId}`, 'PUT', data); closeModal(); showToast('更新成功'); loadPage('agents'); } async function deleteAgent(agentId) { if (!confirm('确定删除此智能体?')) return; await fetchAPI(`/api/admin/agents/${agentId}`, 'DELETE'); showToast('删除成功'); loadPage('agents'); } // ==================== 对话配置页面 ==================== async function loadChatConfigPage(content) { llmConfigs = await fetchAPI('/api/admin/llm'); toolConfigs = await fetchAPI('/api/admin/tools'); const chatConfig = await fetchAPI('/api/admin/chat'); content.innerHTML = `

对话配置

此配置对所有用户的普通对话生效,修改后立即生效。

开启后对话可联网搜索实时信息
已配置工具: ${toolConfigs.map(t => t.tool_id).join(', ')}
发送给模型的对话历史条数
0-2之间,越高越随机创造性,越低越稳定精确

参数说明

🧠 LLM配置

选择对话使用的大模型接口

🔍 启用联网搜索

用户可在对话中开启联网搜索

🔧 可用工具

对话中可使用的工具列表

📜 历史记录数

发送多少条历史对话给模型

`; } function toggleEnableSearch() { const enableSearch = document.getElementById('chatEnableSearch').checked; const toolsInput = document.getElementById('chatEnableTools'); // 自动添加/移除 search 工具 let tools = toolsInput.value.split(',').filter(t => t.trim()); if (enableSearch) { if (!tools.includes('search')) { tools.push('search'); } } else { tools = tools.filter(t => t !== 'search'); } toolsInput.value = tools.join(','); } async function saveChatConfig() { const data = { llm_config_id: parseInt(document.getElementById('chatLLMConfig').value), enable_search: document.getElementById('chatEnableSearch').checked ? 1 : 0, enable_tools: document.getElementById('chatEnableTools').value, max_history: parseInt(document.getElementById('chatMaxHistory').value), temperature: parseFloat(document.getElementById('chatTemperature').value), system_prompt: document.getElementById('chatSystemPrompt').value }; await fetchAPI('/api/admin/chat', 'PUT', data); showToast('保存成功'); loadPage('chat'); } // ==================== 工具配置页面 ==================== async function loadToolsPage(content) { toolConfigs = await fetchAPI('/api/admin/tools'); const toolTypes = { search: '搜索工具', calculator: '计算器', image: '图像生成', code: '代码执行', weather: '天气查询', custom: '自定义' }; content.innerHTML = `

工具配置

${toolConfigs.map(t => ` `).join('')}
工具ID 名称 类型 提供商 API URL 状态 操作
${t.tool_id} ${t.is_default ? '默认' : ''} ${t.name} ${toolTypes[t.type] || t.type} ${t.provider} ${t.api_url} ${t.is_active ? '✅ 启用' : '❌ 禁用'}
${!t.is_default ? `` : ''}

工具类型说明

🔍 search

联网搜索工具(Tavily、Google等)

🧮 calculator

数学计算工具

🎨 image

图像生成工具(DALL-E等)

💻 code

代码执行工具

`; } function showAddToolModal() { showModal('添加工具', `
`); } function showEditToolModal(toolId) { const tool = toolConfigs.find(t => t.tool_id === toolId); if (!tool) return; const toolTypes = ['search', 'calculator', 'image', 'code', 'weather', 'custom']; showModal('编辑工具', `
`); } async function saveTool() { const data = { tool_id: document.getElementById('toolId').value, name: document.getElementById('toolName').value, type: document.getElementById('toolType').value, provider: document.getElementById('toolProvider').value, api_url: document.getElementById('toolApiUrl').value, api_key: document.getElementById('toolApiKey').value, max_results: parseInt(document.getElementById('toolMaxResults').value), config_json: document.getElementById('toolConfigJson').value }; if (!data.tool_id || !data.name || !data.type) { showToast('请填写完整信息'); return; } await fetchAPI('/api/admin/tools', 'POST', data); closeModal(); showToast('添加成功'); loadPage('tools'); } async function updateTool(toolId) { const data = { name: document.getElementById('toolName').value, type: document.getElementById('toolType').value, provider: document.getElementById('toolProvider').value, api_url: document.getElementById('toolApiUrl').value, api_key: document.getElementById('toolApiKey').value, max_results: parseInt(document.getElementById('toolMaxResults').value), config_json: document.getElementById('toolConfigJson').value }; await fetchAPI(`/api/admin/tools/${toolId}`, 'PUT', data); closeModal(); showToast('更新成功'); loadPage('tools'); } async function setDefaultTool(toolId) { await fetchAPI(`/api/admin/tools/${toolId}/default`, 'POST'); showToast('已设为默认'); loadPage('tools'); } async function deleteTool(toolId) { if (!confirm('确定删除此工具?')) return; await fetchAPI(`/api/admin/tools/${toolId}`, 'DELETE'); showToast('删除成功'); loadPage('tools'); } // ==================== 系统设置页面 ==================== async function loadSystemPage(content) { systemConfigs = await fetchAPI('/api/admin/system'); content.innerHTML = `

系统设置

${systemConfigs.app_name?.description || ''}

游客使用限制

管理员设置

💡 提示:启用联网搜索等对话相关配置请前往"对话配置"页面设置

`; } async function saveSystemConfig() { const data = { app_name: document.getElementById('appName').value, app_version: document.getElementById('appVersion').value, guest_chat_sessions: document.getElementById('guestChatSessions').value, guest_chat_messages: document.getElementById('guestChatMessages').value, guest_agent_messages: document.getElementById('guestAgentMessages').value, admin_password: document.getElementById('adminPassword').value }; await fetchAPI('/api/admin/system', 'POST', data); showToast('保存成功'); } // ==================== 工具函数 ==================== async function fetchAPI(url, method = 'GET', data = null) { const options = { method, headers: { 'Content-Type': 'application/json' } }; if (data) { options.body = JSON.stringify(data); } const res = await fetch(`${API_BASE}${url}`, options); return res.json(); } function showModal(title, content) { const modal = document.getElementById('modal'); const modalContent = document.getElementById('modalContent'); modalContent.innerHTML = ` ${content} `; modal.classList.add('show'); } function closeModal() { document.getElementById('modal').classList.remove('show'); } function showToast(message) { const toast = document.getElementById('toast'); toast.textContent = message; toast.classList.add('show'); setTimeout(() => { toast.classList.remove('show'); }, 2000); } // 点击模态框背景关闭 document.getElementById('modal').addEventListener('click', (e) => { if (e.target.id === 'modal') { closeModal(); } });