// 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 => `
| ${a.log_key} |
${a.count} |
`).join('') || '| 暂无数据 |
'}
`;
}
// ==================== 用户管理页面 ====================
let users = [];
async function loadUsersPage(content) {
users = await fetchAPI('/api/admin/users');
content.innerHTML = `
🆕
${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}
已绑定邮箱
| ID |
头像 |
用户名 |
手机号 |
邮箱 |
注册时间 |
最后登录 |
操作 |
${users.length === 0 ? '| 暂无用户 |
' :
users.map(u => `
| ${u.id} |
${u.avatar || '👤'} |
${u.username} |
${u.phone} |
${u.email || '-'} |
${formatDate(u.created_at)} |
${u.last_login_at ? formatDate(u.last_login_at) : '从未登录'} |
|
`).join('')
}
`;
}
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 = `
| 名称 |
提供商 |
模型 |
思考模式 |
视觉能力 |
API URL |
操作 |
${llmConfigs.map(c => `
| ${c.name} ${c.is_default ? '默认' : ''} |
${c.provider} |
${c.model} |
${c.enable_thinking ? '✅ 支持' : '❌ 不支持'} |
${c.enable_vision ? '✅ 支持' : '❌ 不支持'} |
${c.api_url} |
${!c.is_default ? `` : ''}
|
`).join('')}
`;
}
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 => `
| ${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 ? '✅ 已上线' : '❌ 未上线'}
|
|
`).join('')}
说明
标签
hot=热门, popular=推荐, new=新品
`;
}
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 = `
`;
}
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 = `
| 工具ID |
名称 |
类型 |
提供商 |
API URL |
状态 |
操作 |
${toolConfigs.map(t => `
| ${t.tool_id} ${t.is_default ? '默认' : ''} |
${t.name} |
${toolTypes[t.type] || t.type} |
${t.provider} |
${t.api_url} |
${t.is_active ? '✅ 启用' : '❌ 禁用'} |
${!t.is_default ? `` : ''}
|
`).join('')}
工具类型说明
🔍 search
联网搜索工具(Tavily、Google等)
`;
}
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 = `
💡 提示:启用联网搜索等对话相关配置请前往"对话配置"页面设置
`;
}
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();
}
});