// TSP智能助手综合管理平台前端脚本 class TSPDashboard { constructor() { this.currentTab = 'dashboard'; this.charts = {}; this.refreshIntervals = {}; this.websocket = null; this.sessionId = null; this.isAgentMode = true; this.init(); this.restorePageState(); } init() { this.bindEvents(); this.loadInitialData(); this.startAutoRefresh(); this.initCharts(); } bindEvents() { // 标签页切换 document.querySelectorAll('[data-tab]').forEach(tab => { tab.addEventListener('click', (e) => { e.preventDefault(); this.switchTab(tab.dataset.tab); }); }); // 对话控制 document.getElementById('start-chat').addEventListener('click', () => this.startChat()); document.getElementById('end-chat').addEventListener('click', () => this.endChat()); document.getElementById('create-work-order').addEventListener('click', () => this.showCreateWorkOrderModal()); document.getElementById('send-button').addEventListener('click', () => this.sendMessage()); document.getElementById('message-input').addEventListener('keypress', (e) => { if (e.key === 'Enter') this.sendMessage(); }); // 快速操作按钮 document.querySelectorAll('.quick-action-btn').forEach(btn => { btn.addEventListener('click', () => { const message = btn.dataset.message; document.getElementById('message-input').value = message; this.sendMessage(); }); }); // Agent控制 document.getElementById('agent-mode-toggle').addEventListener('change', (e) => { this.toggleAgentMode(e.target.checked); }); document.getElementById('start-agent-monitoring').addEventListener('click', () => this.startAgentMonitoring()); document.getElementById('stop-agent-monitoring').addEventListener('click', () => this.stopAgentMonitoring()); document.getElementById('proactive-monitoring').addEventListener('click', () => this.proactiveMonitoring()); document.getElementById('intelligent-analysis').addEventListener('click', () => this.intelligentAnalysis()); // 预警管理 document.getElementById('refresh-alerts').addEventListener('click', () => this.loadAlerts()); document.getElementById('alert-filter').addEventListener('change', () => this.updateAlertsDisplay()); // 知识库管理 document.getElementById('search-knowledge').addEventListener('click', () => this.searchKnowledge()); document.getElementById('knowledge-search').addEventListener('keypress', (e) => { if (e.key === 'Enter') this.searchKnowledge(); }); // 工单管理 document.getElementById('refresh-workorders').addEventListener('click', () => this.loadWorkOrders()); document.getElementById('workorder-status-filter').addEventListener('change', () => this.loadWorkOrders()); document.getElementById('workorder-priority-filter').addEventListener('change', () => this.loadWorkOrders()); // 模态框 document.getElementById('create-work-order-btn').addEventListener('click', () => this.createWorkOrder()); document.getElementById('add-knowledge-btn').addEventListener('click', () => this.addKnowledge()); document.getElementById('upload-file-btn').addEventListener('click', () => this.uploadFile()); // 置信度滑块 document.getElementById('knowledge-confidence').addEventListener('input', (e) => { document.getElementById('confidence-value').textContent = e.target.value; }); document.getElementById('file-confidence').addEventListener('input', (e) => { document.getElementById('file-confidence-value').textContent = e.target.value; }); // 处理方式选择 document.getElementById('process-method').addEventListener('change', (e) => { const manualDiv = document.getElementById('manual-question-div'); if (e.target.value === 'manual') { manualDiv.style.display = 'block'; } else { manualDiv.style.display = 'none'; } }); // 系统设置 document.getElementById('system-settings-form').addEventListener('submit', (e) => { e.preventDefault(); this.saveSystemSettings(); }); } switchTab(tabName) { // 更新导航状态 document.querySelectorAll('.nav-link').forEach(link => { link.classList.remove('active'); }); document.querySelector(`[data-tab="${tabName}"]`).classList.add('active'); // 显示对应内容 document.querySelectorAll('.tab-content').forEach(content => { content.style.display = 'none'; }); document.getElementById(`${tabName}-tab`).style.display = 'block'; this.currentTab = tabName; // 保存当前页面状态 this.savePageState(); // 加载对应数据 switch(tabName) { case 'dashboard': this.loadDashboardData(); break; case 'chat': this.loadChatData(); break; case 'agent': this.loadAgentData(); break; case 'alerts': this.loadAlerts(); break; case 'knowledge': this.loadKnowledge(); break; case 'workorders': this.loadWorkOrders(); break; case 'analytics': this.loadAnalytics(); break; case 'settings': this.loadSettings(); break; } } savePageState() { const state = { currentTab: this.currentTab, timestamp: Date.now() }; localStorage.setItem('tsp_dashboard_state', JSON.stringify(state)); } restorePageState() { try { const savedState = localStorage.getItem('tsp_dashboard_state'); if (savedState) { const state = JSON.parse(savedState); // 如果状态保存时间不超过1小时,则恢复 if (Date.now() - state.timestamp < 3600000) { this.switchTab(state.currentTab); } } } catch (error) { console.warn('恢复页面状态失败:', error); } } async loadInitialData() { await Promise.all([ this.loadHealth(), this.loadDashboardData(), this.loadSystemInfo() ]); } startAutoRefresh() { // 每5秒刷新健康状态 this.refreshIntervals.health = setInterval(() => { this.loadHealth(); }, 5000); // 每10秒刷新当前标签页数据 this.refreshIntervals.currentTab = setInterval(() => { this.refreshCurrentTab(); }, 10000); } refreshCurrentTab() { switch(this.currentTab) { case 'dashboard': this.loadDashboardData(); break; case 'alerts': this.loadAlerts(); break; case 'agent': this.loadAgentData(); break; } } async loadHealth() { try { const response = await fetch('/api/health'); const data = await response.json(); this.updateHealthDisplay(data); } catch (error) { console.error('加载健康状态失败:', error); } } updateHealthDisplay(health) { const healthScore = health.health_score || 0; const healthStatus = health.health_status || 'unknown'; // 更新健康指示器 const healthDot = document.getElementById('health-dot'); const healthStatusText = document.getElementById('health-status'); const systemHealthDot = document.getElementById('system-health-dot'); const systemHealthText = document.getElementById('system-health-text'); const healthProgress = document.getElementById('health-progress'); if (healthDot) { healthDot.className = `health-dot ${healthStatus}`; } if (healthStatusText) { healthStatusText.textContent = this.getHealthStatusText(healthStatus); } if (systemHealthDot) { systemHealthDot.className = `health-dot ${healthStatus}`; } if (systemHealthText) { systemHealthText.textContent = this.getHealthStatusText(healthStatus); } if (healthProgress) { healthProgress.style.width = `${healthScore * 100}%`; healthProgress.className = `progress-bar ${this.getHealthColor(healthScore)}`; } // 更新内存和CPU使用率 const memoryUsage = health.memory_usage || 0; const memoryProgress = document.getElementById('memory-progress'); if (memoryProgress) { memoryProgress.style.width = `${memoryUsage}%`; } const cpuUsage = health.cpu_usage || 0; const cpuProgress = document.getElementById('cpu-progress'); if (cpuProgress) { cpuProgress.style.width = `${cpuUsage}%`; } } getHealthStatusText(status) { const statusMap = { 'excellent': '优秀', 'good': '良好', 'fair': '一般', 'poor': '较差', 'critical': '严重', 'unknown': '未知' }; return statusMap[status] || status; } getHealthColor(score) { if (score >= 0.8) return 'bg-success'; if (score >= 0.6) return 'bg-info'; if (score >= 0.4) return 'bg-warning'; return 'bg-danger'; } async loadDashboardData() { try { const [sessionsResponse, alertsResponse, workordersResponse, knowledgeResponse] = await Promise.all([ fetch('/api/chat/sessions'), fetch('/api/alerts'), fetch('/api/workorders'), fetch('/api/knowledge/stats') ]); const sessions = await sessionsResponse.json(); const alerts = await alertsResponse.json(); const workorders = await workordersResponse.json(); const knowledge = await knowledgeResponse.json(); // 更新统计卡片 document.getElementById('total-sessions').textContent = sessions.sessions?.length || 0; document.getElementById('total-alerts').textContent = alerts.length || 0; document.getElementById('total-workorders').textContent = workorders.filter(w => w.status === 'open').length || 0; document.getElementById('knowledge-count').textContent = knowledge.total_entries || 0; // 更新知识库详细统计 document.getElementById('knowledge-total').textContent = knowledge.total_entries || 0; document.getElementById('knowledge-active').textContent = knowledge.active_entries || 0; const confidencePercent = Math.round((knowledge.average_confidence || 0) * 100); document.getElementById('knowledge-confidence').style.width = `${confidencePercent}%`; document.getElementById('knowledge-confidence').setAttribute('aria-valuenow', confidencePercent); document.getElementById('knowledge-confidence').textContent = `${confidencePercent}%`; // 更新性能图表 this.updatePerformanceChart(sessions, alerts, workorders); } catch (error) { console.error('加载仪表板数据失败:', error); } } initCharts() { // 性能趋势图 const performanceCtx = document.getElementById('performanceChart'); if (performanceCtx) { this.charts.performance = new Chart(performanceCtx, { type: 'line', data: { labels: [], datasets: [{ label: '活跃会话', data: [], borderColor: '#007bff', backgroundColor: 'rgba(0, 123, 255, 0.1)', tension: 0.4 }, { label: '活跃预警', data: [], borderColor: '#dc3545', backgroundColor: 'rgba(220, 53, 69, 0.1)', tension: 0.4 }] }, options: { responsive: true, maintainAspectRatio: false, scales: { y: { beginAtZero: true } } } }); } // 分析图表 const analyticsCtx = document.getElementById('analyticsChart'); if (analyticsCtx) { this.charts.analytics = new Chart(analyticsCtx, { type: 'line', data: { labels: [], datasets: [{ label: '满意度', data: [], borderColor: '#28a745', backgroundColor: 'rgba(40, 167, 69, 0.1)', tension: 0.4 }, { label: '解决时间(小时)', data: [], borderColor: '#ffc107', backgroundColor: 'rgba(255, 193, 7, 0.1)', tension: 0.4 }] }, options: { responsive: true, maintainAspectRatio: false, scales: { y: { beginAtZero: true } } } }); } // 类别分布图 const categoryCtx = document.getElementById('categoryChart'); if (categoryCtx) { this.charts.category = new Chart(categoryCtx, { type: 'doughnut', data: { labels: [], datasets: [{ data: [], backgroundColor: [ '#007bff', '#28a745', '#ffc107', '#dc3545', '#17a2b8' ] }] }, options: { responsive: true, maintainAspectRatio: false } }); } } updatePerformanceChart(sessions, alerts, workorders) { if (!this.charts.performance) return; const now = new Date(); const labels = []; const sessionData = []; const alertData = []; // 生成过去24小时的数据点 for (let i = 23; i >= 0; i--) { const time = new Date(now.getTime() - i * 60 * 60 * 1000); labels.push(time.getHours() + ':00'); sessionData.push(Math.floor(Math.random() * 10) + 5); // 模拟数据 alertData.push(Math.floor(Math.random() * 5)); // 模拟数据 } this.charts.performance.data.labels = labels; this.charts.performance.data.datasets[0].data = sessionData; this.charts.performance.data.datasets[1].data = alertData; this.charts.performance.update(); } // 对话功能 async startChat() { try { const userId = document.getElementById('user-id').value; const workOrderId = document.getElementById('work-order-id').value; const response = await fetch('/api/chat/session', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ user_id: userId, work_order_id: workOrderId ? parseInt(workOrderId) : null }) }); const data = await response.json(); if (data.success) { this.sessionId = data.session_id; document.getElementById('start-chat').disabled = true; document.getElementById('end-chat').disabled = false; document.getElementById('message-input').disabled = false; document.getElementById('send-button').disabled = false; document.getElementById('session-info').textContent = `会话ID: ${this.sessionId}`; document.getElementById('connection-status').className = 'badge bg-success'; document.getElementById('connection-status').innerHTML = '已连接'; this.showNotification('对话已开始', 'success'); } else { this.showNotification('开始对话失败', 'error'); } } catch (error) { console.error('开始对话失败:', error); this.showNotification('开始对话失败', 'error'); } } async endChat() { try { if (!this.sessionId) return; const response = await fetch(`/api/chat/session/${this.sessionId}`, { method: 'DELETE' }); const data = await response.json(); if (data.success) { this.sessionId = null; document.getElementById('start-chat').disabled = false; document.getElementById('end-chat').disabled = true; document.getElementById('message-input').disabled = true; document.getElementById('send-button').disabled = true; document.getElementById('session-info').textContent = '未开始对话'; document.getElementById('connection-status').className = 'badge bg-secondary'; document.getElementById('connection-status').innerHTML = '未连接'; this.showNotification('对话已结束', 'info'); } else { this.showNotification('结束对话失败', 'error'); } } catch (error) { console.error('结束对话失败:', error); this.showNotification('结束对话失败', 'error'); } } async sendMessage() { const messageInput = document.getElementById('message-input'); const message = messageInput.value.trim(); if (!message || !this.sessionId) return; // 显示用户消息 this.addMessage('user', message); messageInput.value = ''; // 发送消息到服务器 try { const response = await fetch('/api/chat/message', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ session_id: this.sessionId, message: message }) }); const data = await response.json(); if (data.success) { this.addMessage('assistant', data.response, data.knowledge_used); } else { this.addMessage('assistant', '抱歉,处理您的消息时出现了错误。', null, true); } } catch (error) { console.error('发送消息失败:', error); this.addMessage('assistant', '网络连接错误,请稍后重试。', null, true); } } addMessage(role, content, knowledgeUsed = null, isError = false) { const messagesContainer = document.getElementById('chat-messages'); // 移除欢迎消息 const welcomeMsg = messagesContainer.querySelector('.text-center'); if (welcomeMsg) { welcomeMsg.remove(); } const messageDiv = document.createElement('div'); messageDiv.className = `message ${role}`; const avatar = document.createElement('div'); avatar.className = 'message-avatar'; avatar.innerHTML = role === 'user' ? '' : ''; const contentDiv = document.createElement('div'); contentDiv.className = 'message-content'; contentDiv.innerHTML = `
${content}
${new Date().toLocaleTimeString()}
`; if (knowledgeUsed && knowledgeUsed.length > 0) { const knowledgeDiv = document.createElement('div'); knowledgeDiv.className = 'knowledge-info'; knowledgeDiv.innerHTML = ` 使用了知识库: ${knowledgeUsed.map(k => k.question).join(', ')} `; contentDiv.appendChild(knowledgeDiv); } if (isError) { contentDiv.style.borderLeft = '4px solid #dc3545'; } messageDiv.appendChild(avatar); messageDiv.appendChild(contentDiv); messagesContainer.appendChild(messageDiv); // 滚动到底部 messagesContainer.scrollTop = messagesContainer.scrollHeight; } // Agent功能 async toggleAgentMode(enabled) { try { const response = await fetch('/api/agent/toggle', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ enabled }) }); const data = await response.json(); if (data.success) { this.isAgentMode = enabled; this.showNotification(`Agent模式已${enabled ? '启用' : '禁用'}`, 'success'); this.loadAgentData(); } else { this.showNotification('切换Agent模式失败', 'error'); } } catch (error) { console.error('切换Agent模式失败:', error); this.showNotification('切换Agent模式失败', 'error'); } } async loadAgentData() { try { const response = await fetch('/api/agent/status'); const data = await response.json(); if (data.success) { document.getElementById('agent-current-state').textContent = data.status || '未知'; document.getElementById('agent-active-goals').textContent = data.active_goals || 0; document.getElementById('agent-available-tools').textContent = data.available_tools || 0; // 更新工具列表 this.updateToolsList(data.tools || []); // 更新执行历史 this.updateExecutionHistory(data.execution_history || []); } } catch (error) { console.error('加载Agent数据失败:', error); } } updateToolsList(tools) { const toolsList = document.getElementById('tools-list'); if (tools.length === 0) { toolsList.innerHTML = '

暂无工具

'; return; } const toolsHtml = tools.map(tool => `
${tool.name}
使用次数: ${tool.usage_count || 0}
${Math.round((tool.success_rate || 0) * 100)}%
`).join(''); toolsList.innerHTML = toolsHtml; } updateExecutionHistory(history) { const historyContainer = document.getElementById('agent-execution-history'); if (history.length === 0) { historyContainer.innerHTML = '

暂无执行历史

'; return; } const historyHtml = history.slice(-5).map(item => `
${item.type || '未知任务'} ${new Date(item.timestamp).toLocaleString()}
${item.description || '无描述'}
${item.success ? '成功' : '失败'}
`).join(''); historyContainer.innerHTML = historyHtml; } async startAgentMonitoring() { try { const response = await fetch('/api/agent/monitoring/start', { method: 'POST' }); const data = await response.json(); if (data.success) { this.showNotification('Agent监控已启动', 'success'); } else { this.showNotification('启动Agent监控失败', 'error'); } } catch (error) { console.error('启动Agent监控失败:', error); this.showNotification('启动Agent监控失败', 'error'); } } async stopAgentMonitoring() { try { const response = await fetch('/api/agent/monitoring/stop', { method: 'POST' }); const data = await response.json(); if (data.success) { this.showNotification('Agent监控已停止', 'success'); } else { this.showNotification('停止Agent监控失败', 'error'); } } catch (error) { console.error('停止Agent监控失败:', error); this.showNotification('停止Agent监控失败', 'error'); } } async proactiveMonitoring() { try { const response = await fetch('/api/agent/proactive-monitoring', { method: 'POST' }); const data = await response.json(); if (data.success) { this.showNotification(`主动监控完成,发现 ${data.proactive_actions?.length || 0} 个行动机会`, 'info'); } else { this.showNotification('主动监控失败', 'error'); } } catch (error) { console.error('主动监控失败:', error); this.showNotification('主动监控失败', 'error'); } } async intelligentAnalysis() { try { const response = await fetch('/api/agent/intelligent-analysis', { method: 'POST' }); const data = await response.json(); if (data.success) { this.showNotification('智能分析完成', 'success'); // 更新分析图表 this.updateAnalyticsChart(data.analysis); } else { this.showNotification('智能分析失败', 'error'); } } catch (error) { console.error('智能分析失败:', error); this.showNotification('智能分析失败', 'error'); } } updateAnalyticsChart(analysis) { if (!this.charts.analytics || !analysis) return; // 更新分析图表数据 const labels = analysis.trends?.dates || []; const satisfactionData = analysis.trends?.satisfaction || []; const resolutionTimeData = analysis.trends?.resolution_time || []; this.charts.analytics.data.labels = labels; this.charts.analytics.data.datasets[0].data = satisfactionData; this.charts.analytics.data.datasets[1].data = resolutionTimeData; this.charts.analytics.update(); } // 预警管理 async loadAlerts() { try { const response = await fetch('/api/alerts'); const alerts = await response.json(); this.updateAlertsDisplay(alerts); this.updateAlertStatistics(alerts); } catch (error) { console.error('加载预警失败:', error); } } updateAlertsDisplay(alerts) { const container = document.getElementById('alerts-container'); if (alerts.length === 0) { container.innerHTML = `
暂无活跃预警

系统运行正常,没有需要处理的预警

`; return; } const alertsHtml = alerts.map(alert => `
${this.getLevelText(alert.level)} ${alert.rule_name || '未知规则'} ${this.formatTime(alert.created_at)}
${alert.message}
类型: ${this.getTypeText(alert.alert_type)} | 级别: ${this.getLevelText(alert.level)}
`).join(''); container.innerHTML = alertsHtml; } updateAlertStatistics(alerts) { const stats = alerts.reduce((acc, alert) => { acc[alert.level] = (acc[alert.level] || 0) + 1; acc.total = (acc.total || 0) + 1; return acc; }, {}); document.getElementById('critical-alerts').textContent = stats.critical || 0; document.getElementById('warning-alerts').textContent = stats.warning || 0; document.getElementById('info-alerts').textContent = stats.info || 0; document.getElementById('total-alerts-count').textContent = stats.total || 0; } async resolveAlert(alertId) { try { const response = await fetch(`/api/alerts/${alertId}/resolve`, { method: 'POST' }); const data = await response.json(); if (data.success) { this.showNotification('预警已解决', 'success'); this.loadAlerts(); } else { this.showNotification('解决预警失败', 'error'); } } catch (error) { console.error('解决预警失败:', error); this.showNotification('解决预警失败', 'error'); } } // 知识库管理 async loadKnowledge(page = 1) { try { const response = await fetch(`/api/knowledge?page=${page}&per_page=10`); const data = await response.json(); if (data.knowledge) { this.updateKnowledgeDisplay(data.knowledge); this.updateKnowledgePagination(data); } else { // 兼容旧格式 this.updateKnowledgeDisplay(data); } } catch (error) { console.error('加载知识库失败:', error); } } updateKnowledgeDisplay(knowledge) { const container = document.getElementById('knowledge-list'); if (knowledge.length === 0) { container.innerHTML = '

暂无知识条目

'; return; } const knowledgeHtml = knowledge.map(item => `
${item.question}

${item.answer}

分类: ${item.category} 置信度: ${Math.round(item.confidence_score * 100)}% 使用次数: ${item.usage_count || 0} ${item.is_verified ? '已验证' : '未验证'}
${item.is_verified ? `` : `` }
`).join(''); container.innerHTML = knowledgeHtml; } updateKnowledgePagination(data) { const paginationContainer = document.getElementById('knowledge-pagination'); if (!paginationContainer) return; const { page, total_pages, total } = data; if (total_pages <= 1) { paginationContainer.innerHTML = ''; return; } let paginationHtml = `
共 ${total} 条知识,第 ${page} / ${total_pages} 页
`; paginationContainer.innerHTML = paginationHtml; } async searchKnowledge() { const query = document.getElementById('knowledge-search').value.trim(); if (!query) { this.loadKnowledge(); return; } try { const response = await fetch(`/api/knowledge/search?q=${encodeURIComponent(query)}`); const results = await response.json(); this.updateKnowledgeDisplay(results); } catch (error) { console.error('搜索知识库失败:', error); } } async addKnowledge() { const question = document.getElementById('knowledge-question').value.trim(); const answer = document.getElementById('knowledge-answer').value.trim(); const category = document.getElementById('knowledge-category').value; const confidence = parseFloat(document.getElementById('knowledge-confidence').value); if (!question || !answer) { this.showNotification('请填写完整信息', 'warning'); return; } try { const response = await fetch('/api/knowledge', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ question, answer, category, confidence_score: confidence }) }); const data = await response.json(); if (data.success) { this.showNotification('知识添加成功', 'success'); bootstrap.Modal.getInstance(document.getElementById('addKnowledgeModal')).hide(); document.getElementById('knowledge-form').reset(); this.loadKnowledge(); } else { this.showNotification('添加知识失败', 'error'); } } catch (error) { console.error('添加知识失败:', error); this.showNotification('添加知识失败', 'error'); } } async uploadFile() { const fileInput = document.getElementById('file-input'); const processMethod = document.getElementById('process-method').value; const category = document.getElementById('file-category').value; const confidence = parseFloat(document.getElementById('file-confidence').value); const manualQuestion = document.getElementById('manual-question').value.trim(); if (!fileInput.files[0]) { this.showNotification('请选择文件', 'warning'); return; } if (processMethod === 'manual' && !manualQuestion) { this.showNotification('请指定问题', 'warning'); return; } // 显示进度条 const progressDiv = document.getElementById('upload-progress'); const progressBar = progressDiv.querySelector('.progress-bar'); const statusText = document.getElementById('upload-status'); progressDiv.style.display = 'block'; progressBar.style.width = '0%'; statusText.textContent = '正在上传文件...'; try { const formData = new FormData(); formData.append('file', fileInput.files[0]); formData.append('process_method', processMethod); formData.append('category', category); formData.append('confidence_score', confidence); if (manualQuestion) { formData.append('manual_question', manualQuestion); } // 模拟进度更新 let progress = 0; const progressInterval = setInterval(() => { progress += Math.random() * 20; if (progress > 90) progress = 90; progressBar.style.width = progress + '%'; if (progress < 30) { statusText.textContent = '正在上传文件...'; } else if (progress < 60) { statusText.textContent = '正在解析文件内容...'; } else if (progress < 90) { statusText.textContent = '正在生成知识库...'; } }, 500); const response = await fetch('/api/knowledge/upload', { method: 'POST', body: formData }); clearInterval(progressInterval); progressBar.style.width = '100%'; statusText.textContent = '处理完成!'; const data = await response.json(); setTimeout(() => { progressDiv.style.display = 'none'; if (data.success) { this.showNotification(`文件处理成功,生成了 ${data.knowledge_count || 0} 条知识`, 'success'); bootstrap.Modal.getInstance(document.getElementById('uploadFileModal')).hide(); document.getElementById('file-upload-form').reset(); this.loadKnowledge(); } else { this.showNotification(data.error || '文件处理失败', 'error'); } }, 1000); } catch (error) { console.error('文件上传失败:', error); progressDiv.style.display = 'none'; this.showNotification('文件上传失败', 'error'); } } async verifyKnowledge(knowledgeId) { try { const response = await fetch(`/api/knowledge/verify/${knowledgeId}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ verified_by: 'admin' }) }); const data = await response.json(); if (data.success) { this.showNotification('知识库验证成功', 'success'); this.loadKnowledge(); } else { this.showNotification('知识库验证失败', 'error'); } } catch (error) { console.error('验证知识库失败:', error); this.showNotification('验证知识库失败', 'error'); } } async unverifyKnowledge(knowledgeId) { try { const response = await fetch(`/api/knowledge/unverify/${knowledgeId}`, { method: 'POST', headers: { 'Content-Type': 'application/json' } }); const data = await response.json(); if (data.success) { this.showNotification('取消验证成功', 'success'); this.loadKnowledge(); } else { this.showNotification('取消验证失败', 'error'); } } catch (error) { console.error('取消验证失败:', error); this.showNotification('取消验证失败', 'error'); } } async deleteKnowledge(knowledgeId) { if (!confirm('确定要删除这条知识库条目吗?')) { return; } try { const response = await fetch(`/api/knowledge/delete/${knowledgeId}`, { method: 'DELETE' }); const data = await response.json(); if (data.success) { this.showNotification('知识库删除成功', 'success'); this.loadKnowledge(); } else { this.showNotification('知识库删除失败', 'error'); } } catch (error) { console.error('删除知识库失败:', error); this.showNotification('删除知识库失败', 'error'); } } // 工单管理 async loadWorkOrders() { try { const statusFilter = document.getElementById('workorder-status-filter').value; const priorityFilter = document.getElementById('workorder-priority-filter').value; let url = '/api/workorders'; const params = new URLSearchParams(); if (statusFilter !== 'all') params.append('status', statusFilter); if (priorityFilter !== 'all') params.append('priority', priorityFilter); if (params.toString()) url += '?' + params.toString(); const response = await fetch(url); const workorders = await response.json(); this.updateWorkOrdersDisplay(workorders); this.updateWorkOrderStatistics(workorders); } catch (error) { console.error('加载工单失败:', error); } } updateWorkOrdersDisplay(workorders) { const container = document.getElementById('workorders-list'); if (workorders.length === 0) { container.innerHTML = '

暂无工单

'; return; } const workordersHtml = workorders.map(workorder => `
${workorder.title}

${workorder.description}

${this.getPriorityText(workorder.priority)} ${this.getStatusText(workorder.status)} 分类: ${workorder.category} 创建时间: ${new Date(workorder.created_at).toLocaleString()}
`).join(''); container.innerHTML = workordersHtml; } updateWorkOrderStatistics(workorders) { const stats = workorders.reduce((acc, wo) => { acc.total = (acc.total || 0) + 1; acc[wo.status] = (acc[wo.status] || 0) + 1; return acc; }, {}); document.getElementById('workorders-total').textContent = stats.total || 0; document.getElementById('workorders-open').textContent = stats.open || 0; document.getElementById('workorders-progress').textContent = stats.in_progress || 0; document.getElementById('workorders-resolved').textContent = stats.resolved || 0; } async createWorkOrder() { const title = document.getElementById('wo-title').value.trim(); const description = document.getElementById('wo-description').value.trim(); const category = document.getElementById('wo-category').value; const priority = document.getElementById('wo-priority').value; if (!title || !description) { this.showNotification('请填写完整信息', 'warning'); return; } try { const response = await fetch('/api/workorders', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ title, description, category, priority }) }); const data = await response.json(); if (data.success) { this.showNotification('工单创建成功', 'success'); bootstrap.Modal.getInstance(document.getElementById('createWorkOrderModal')).hide(); document.getElementById('work-order-form').reset(); this.loadWorkOrders(); } else { this.showNotification('创建工单失败', 'error'); } } catch (error) { console.error('创建工单失败:', error); this.showNotification('创建工单失败', 'error'); } } // 数据分析 async loadAnalytics() { try { const response = await fetch('/api/analytics'); const analytics = await response.json(); this.updateAnalyticsDisplay(analytics); } catch (error) { console.error('加载分析数据失败:', error); } } updateAnalyticsDisplay(analytics) { // 更新分析报告 const reportContainer = document.getElementById('analytics-report'); if (analytics.summary) { reportContainer.innerHTML = `
性能指标
趋势分析
`; } // 更新类别分布图 if (analytics.category_distribution && this.charts.category) { const labels = Object.keys(analytics.category_distribution); const data = Object.values(analytics.category_distribution); this.charts.category.data.labels = labels; this.charts.category.data.datasets[0].data = data; this.charts.category.update(); } } // 系统设置 async loadSettings() { try { const response = await fetch('/api/settings'); const settings = await response.json(); this.updateSettingsDisplay(settings); } catch (error) { console.error('加载设置失败:', error); } } updateSettingsDisplay(settings) { if (settings.api_timeout) document.getElementById('api-timeout').value = settings.api_timeout; if (settings.max_history) document.getElementById('max-history').value = settings.max_history; if (settings.refresh_interval) document.getElementById('refresh-interval').value = settings.refresh_interval; if (settings.auto_monitoring !== undefined) document.getElementById('auto-monitoring').checked = settings.auto_monitoring; if (settings.agent_mode !== undefined) document.getElementById('agent-mode').checked = settings.agent_mode; } async saveSystemSettings() { const settings = { api_timeout: parseInt(document.getElementById('api-timeout').value), max_history: parseInt(document.getElementById('max-history').value), refresh_interval: parseInt(document.getElementById('refresh-interval').value), auto_monitoring: document.getElementById('auto-monitoring').checked, agent_mode: document.getElementById('agent-mode').checked }; try { const response = await fetch('/api/settings', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(settings) }); const data = await response.json(); if (data.success) { this.showNotification('设置保存成功', 'success'); } else { this.showNotification('保存设置失败', 'error'); } } catch (error) { console.error('保存设置失败:', error); this.showNotification('保存设置失败', 'error'); } } async loadSystemInfo() { try { const response = await fetch('/api/system/info'); const info = await response.json(); this.updateSystemInfoDisplay(info); } catch (error) { console.error('加载系统信息失败:', error); } } updateSystemInfoDisplay(info) { const container = document.getElementById('system-info'); container.innerHTML = `
系统版本: ${info.version || '1.0.0'}
Python版本: ${info.python_version || '未知'}
数据库: ${info.database || 'SQLite'}
运行时间: ${info.uptime || '未知'}
内存使用: ${info.memory_usage || '0'} MB
`; } // 工具函数 getLevelText(level) { const levelMap = { 'critical': '严重', 'error': '错误', 'warning': '警告', 'info': '信息' }; return levelMap[level] || level; } getTypeText(type) { const typeMap = { 'performance': '性能', 'quality': '质量', 'volume': '量级', 'system': '系统', 'business': '业务' }; return typeMap[type] || type; } getAlertColor(level) { const colorMap = { 'critical': 'danger', 'error': 'danger', 'warning': 'warning', 'info': 'info' }; return colorMap[level] || 'secondary'; } getPriorityText(priority) { const priorityMap = { 'low': '低', 'medium': '中', 'high': '高', 'urgent': '紧急' }; return priorityMap[priority] || priority; } getPriorityColor(priority) { const colorMap = { 'low': 'secondary', 'medium': 'primary', 'high': 'warning', 'urgent': 'danger' }; return colorMap[priority] || 'secondary'; } getStatusText(status) { const statusMap = { 'open': '待处理', 'in_progress': '处理中', 'resolved': '已解决', 'closed': '已关闭' }; return statusMap[status] || status; } getStatusColor(status) { const colorMap = { 'open': 'warning', 'in_progress': 'info', 'resolved': 'success', 'closed': 'secondary' }; return colorMap[status] || 'secondary'; } formatTime(timestamp) { const date = new Date(timestamp); const now = new Date(); const diff = now - date; if (diff < 60000) { // 1分钟内 return '刚刚'; } else if (diff < 3600000) { // 1小时内 return `${Math.floor(diff / 60000)}分钟前`; } else if (diff < 86400000) { // 1天内 return `${Math.floor(diff / 3600000)}小时前`; } else { return date.toLocaleDateString(); } } showNotification(message, type = 'info') { const notification = document.createElement('div'); notification.className = `notification alert alert-${type === 'error' ? 'danger' : type} alert-dismissible fade show`; notification.innerHTML = ` ${message} `; document.body.appendChild(notification); setTimeout(() => { if (notification.parentNode) { notification.parentNode.removeChild(notification); } }, 3000); } showCreateWorkOrderModal() { const modal = new bootstrap.Modal(document.getElementById('createWorkOrderModal')); modal.show(); } } // 初始化应用 let dashboard; document.addEventListener('DOMContentLoaded', () => { dashboard = new TSPDashboard(); });