feat: 优化数据分析页面,添加Excel工单导入功能
- 优化数据分析页面,添加可定制的图表功能 - 支持多种图表类型:折线图、柱状图、饼图、环形图、雷达图、极坐标图 - 添加图表定制功能:时间范围选择、数据维度选择 - 实现Excel工单导入功能,支持详情.xlsx文件 - 添加工单编辑功能,包括前端UI和后端API - 修复WebSocket连接错误,处理invalid Connection header问题 - 简化预警管理参数,改为卡片式选择 - 实现Agent主动调用,无需人工干预 - 改进知识库导入,结合累计工单内容与大模型输出
This commit is contained in:
@@ -2408,3 +2408,704 @@ WHERE knowledge_entries.is_active = true AND knowledge_entries.is_verified = tru
|
||||
2025-09-08 15:24:31,102 - werkzeug - INFO - 127.0.0.1 - - [08/Sep/2025 15:24:31] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-08 15:25:31,094 - werkzeug - INFO - 127.0.0.1 - - [08/Sep/2025 15:25:31] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-08 15:26:31,092 - werkzeug - INFO - 127.0.0.1 - - [08/Sep/2025 15:26:31] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-08 15:27:31,139 - werkzeug - INFO - 127.0.0.1 - - [08/Sep/2025 15:27:31] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-08 15:28:31,130 - werkzeug - INFO - 127.0.0.1 - - [08/Sep/2025 15:28:31] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-08 15:29:31,187 - werkzeug - INFO - 127.0.0.1 - - [08/Sep/2025 15:29:31] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-08 15:30:31,159 - werkzeug - INFO - 127.0.0.1 - - [08/Sep/2025 15:30:31] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-08 15:31:31,136 - werkzeug - INFO - 127.0.0.1 - - [08/Sep/2025 15:31:31] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-08 15:32:31,146 - werkzeug - INFO - 127.0.0.1 - - [08/Sep/2025 15:32:31] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-08 15:33:31,133 - werkzeug - INFO - 127.0.0.1 - - [08/Sep/2025 15:33:31] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-08 15:35:40,176 - werkzeug - INFO - 127.0.0.1 - - [08/Sep/2025 15:35:40] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-08 15:36:31,097 - werkzeug - INFO - 127.0.0.1 - - [08/Sep/2025 15:36:31] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-08 15:37:31,132 - werkzeug - INFO - 127.0.0.1 - - [08/Sep/2025 15:37:31] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-08 15:38:31,102 - werkzeug - INFO - 127.0.0.1 - - [08/Sep/2025 15:38:31] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-08 15:39:31,100 - werkzeug - INFO - 127.0.0.1 - - [08/Sep/2025 15:39:31] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-08 15:40:31,116 - werkzeug - INFO - 127.0.0.1 - - [08/Sep/2025 15:40:31] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-08 15:41:31,099 - werkzeug - INFO - 127.0.0.1 - - [08/Sep/2025 15:41:31] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-08 15:43:00,051 - werkzeug - INFO - 127.0.0.1 - - [08/Sep/2025 15:43:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-08 15:43:31,110 - werkzeug - INFO - 127.0.0.1 - - [08/Sep/2025 15:43:31] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:36:01,003 - __main__ - INFO - 正在启动TSP智能助手综合管理平台...
|
||||
2025-09-10 22:36:02,691 - src.core.database - INFO - 数据库初始化成功
|
||||
2025-09-10 22:36:05,024 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 48 个条目
|
||||
2025-09-10 22:36:05,034 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 48 个条目
|
||||
2025-09-10 22:36:05,035 - src.main - INFO - TSP助手初始化完成
|
||||
2025-09-10 22:36:05,044 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 48 个条目
|
||||
2025-09-10 22:36:05,051 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 48 个条目
|
||||
2025-09-10 22:36:05,052 - src.main - INFO - TSP助手初始化完成
|
||||
2025-09-10 22:36:05,052 - src.agent.tool_manager - INFO - 注册工具: search_knowledge
|
||||
2025-09-10 22:36:05,052 - src.agent.tool_manager - INFO - 注册工具: create_work_order
|
||||
2025-09-10 22:36:05,053 - src.agent.tool_manager - INFO - 注册工具: update_work_order
|
||||
2025-09-10 22:36:05,053 - src.agent.tool_manager - INFO - 注册工具: generate_response
|
||||
2025-09-10 22:36:05,053 - src.agent.tool_manager - INFO - 注册工具: analyze_data
|
||||
2025-09-10 22:36:05,053 - src.agent.tool_manager - INFO - 注册工具: send_notification
|
||||
2025-09-10 22:36:05,053 - src.agent.tool_manager - INFO - 注册工具: schedule_task
|
||||
2025-09-10 22:36:05,053 - src.agent.tool_manager - INFO - 注册工具: web_search
|
||||
2025-09-10 22:36:05,053 - src.agent.tool_manager - INFO - 注册工具: file_operation
|
||||
2025-09-10 22:36:05,053 - src.agent.tool_manager - INFO - 注册工具: database_query
|
||||
2025-09-10 22:36:05,054 - src.agent.tool_manager - INFO - 已注册 10 个默认工具
|
||||
2025-09-10 22:36:05,054 - src.agent.agent_core - INFO - Agent核心初始化完成
|
||||
2025-09-10 22:36:05,054 - src.agent_assistant - INFO - TSP Agent助手初始化完成
|
||||
2025-09-10 22:36:05,063 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 48 个条目
|
||||
2025-09-10 22:36:05,142 - werkzeug - INFO - [31m[1mWARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.[0m
|
||||
* Running on all addresses (0.0.0.0)
|
||||
* Running on http://127.0.0.1:5000
|
||||
* Running on http://192.168.26.238:5000
|
||||
2025-09-10 22:36:05,143 - werkzeug - INFO - [33mPress CTRL+C to quit[0m
|
||||
2025-09-10 22:36:05,179 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 48 个条目
|
||||
2025-09-10 22:36:05,183 - src.web.websocket_server - INFO - 启动WebSocket服务器: ws://localhost:8765
|
||||
2025-09-10 22:36:05,188 - websockets.server - INFO - server listening on [::1]:8765
|
||||
2025-09-10 22:36:05,189 - websockets.server - INFO - server listening on 127.0.0.1:8765
|
||||
2025-09-10 22:36:11,102 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:36:11] "GET / HTTP/1.1" 200 -
|
||||
2025-09-10 22:36:11,437 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:36:11] "GET /static/js/dashboard.js HTTP/1.1" 200 -
|
||||
2025-09-10 22:36:13,910 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:36:13] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:36:14,178 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:36:14] "GET /api/chat/sessions HTTP/1.1" 200 -
|
||||
2025-09-10 22:36:14,179 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:36:14] "GET /api/workorders HTTP/1.1" 200 -
|
||||
2025-09-10 22:36:14,194 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:36:14] "GET /api/system/info HTTP/1.1" 200 -
|
||||
2025-09-10 22:36:14,214 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:36:14] "GET /api/knowledge/stats HTTP/1.1" 200 -
|
||||
2025-09-10 22:36:14,214 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:36:14] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 22:36:14,274 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:36:14] "[33mGET /favicon.ico HTTP/1.1[0m" 404 -
|
||||
2025-09-10 22:36:16,244 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:36:16] "GET /api/agent/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:36:17,442 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:36:17] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 22:36:18,891 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:36:18] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:36:19,231 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:36:19] "GET /api/knowledge?page=1&per_page=10 HTTP/1.1" 200 -
|
||||
2025-09-10 22:36:23,885 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:36:23] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:36:24,491 - src.knowledge_base.knowledge_manager - INFO - 知识库条目取消验证成功: 61
|
||||
2025-09-10 22:36:24,492 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:36:24] "POST /api/knowledge/unverify/61 HTTP/1.1" 200 -
|
||||
2025-09-10 22:36:24,721 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:36:24] "GET /api/knowledge?page=1&per_page=10 HTTP/1.1" 200 -
|
||||
2025-09-10 22:36:25,932 - src.knowledge_base.knowledge_manager - INFO - 知识库条目验证成功: 61
|
||||
2025-09-10 22:36:25,933 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:36:25] "POST /api/knowledge/verify/61 HTTP/1.1" 200 -
|
||||
2025-09-10 22:36:26,245 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:36:26] "GET /api/knowledge?page=1&per_page=10 HTTP/1.1" 200 -
|
||||
2025-09-10 22:36:27,241 - src.knowledge_base.knowledge_manager - INFO - 知识库条目验证成功: 51
|
||||
2025-09-10 22:36:27,242 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:36:27] "POST /api/knowledge/verify/51 HTTP/1.1" 200 -
|
||||
2025-09-10 22:36:27,565 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:36:27] "GET /api/knowledge?page=1&per_page=10 HTTP/1.1" 200 -
|
||||
2025-09-10 22:36:28,405 - src.knowledge_base.knowledge_manager - INFO - 知识库条目验证成功: 52
|
||||
2025-09-10 22:36:28,406 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:36:28] "POST /api/knowledge/verify/52 HTTP/1.1" 200 -
|
||||
2025-09-10 22:36:28,726 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:36:28] "GET /api/knowledge?page=1&per_page=10 HTTP/1.1" 200 -
|
||||
2025-09-10 22:36:29,000 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:36:29] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:36:29,824 - src.knowledge_base.knowledge_manager - INFO - 知识库条目验证成功: 53
|
||||
2025-09-10 22:36:29,825 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:36:29] "POST /api/knowledge/verify/53 HTTP/1.1" 200 -
|
||||
2025-09-10 22:36:30,137 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:36:30] "GET /api/knowledge?page=1&per_page=10 HTTP/1.1" 200 -
|
||||
2025-09-10 22:36:31,290 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:36:31] "GET /api/workorders HTTP/1.1" 200 -
|
||||
2025-09-10 22:36:33,343 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:36:33] "GET /api/workorders/1 HTTP/1.1" 200 -
|
||||
2025-09-10 22:36:33,886 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:36:33] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:36:39,194 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:36:39] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:36:42,193 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:36:42] "GET /api/workorders/1 HTTP/1.1" 200 -
|
||||
2025-09-10 22:36:44,196 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:36:44] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:36:47,972 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:36:47] "GET /api/analytics HTTP/1.1" 200 -
|
||||
2025-09-10 22:36:49,206 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:36:49] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:36:50,882 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:36:50] "GET /api/agent/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:36:53,493 - src.analytics.monitor_service - INFO - 监控服务已启动
|
||||
2025-09-10 22:36:53,494 - src.main - INFO - 监控服务已启动
|
||||
2025-09-10 22:36:53,495 - src.agent.auto_monitor - INFO - 自动监控循环已启动
|
||||
2025-09-10 22:36:53,495 - src.agent.auto_monitor - INFO - 自动监控服务已启动
|
||||
2025-09-10 22:36:53,496 - src.agent.auto_monitor - INFO - 执行第 1 次自动监控检查
|
||||
2025-09-10 22:36:53,496 - src.agent_assistant - INFO - 主动监控已启动
|
||||
2025-09-10 22:36:53,497 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:36:53] "POST /api/agent/monitoring/start HTTP/1.1" 200 -
|
||||
2025-09-10 22:36:53,535 - src.agent.auto_monitor - INFO - 触发主动行动: alert_overflow - 活跃预警数量过多: 17
|
||||
2025-09-10 22:36:53,536 - src.agent.auto_monitor - INFO - 主动行动记录: {"timestamp": "2025-09-10T22:36:53.536449", "action_type": "alert_overflow", "priority": "high", "description": "活跃预警数量过多: 17", "action": "建议立即处理预警", "data": {"alert_count": 17}}
|
||||
2025-09-10 22:36:53,537 - src.agent.auto_monitor - INFO - 处理预警溢出
|
||||
2025-09-10 22:36:53,537 - src.agent.auto_monitor - ERROR - 检查工单积压失败: 'TSPAgentAssistant' object has no attribute 'get_workorders'
|
||||
2025-09-10 22:36:53,552 - src.analytics.monitor_service - INFO - 触发 3 个预警
|
||||
2025-09-10 22:36:53,552 - src.analytics.monitor_service - WARNING - 预警触发: 用户满意度较低: 0.00 (阈值: 0.6)
|
||||
2025-09-10 22:36:53,552 - src.analytics.monitor_service - INFO - 发送通知: {'level': '警告', 'message': '用户满意度较低: 0.00 (阈值: 0.6)', 'timestamp': '2025-09-10T22:36:53.511361', 'rule_name': '满意度预警'}
|
||||
2025-09-10 22:36:53,552 - src.analytics.monitor_service - WARNING - 警告预警: 用户满意度较低: 0.00 (阈值: 0.6)
|
||||
2025-09-10 22:36:53,553 - src.analytics.monitor_service - WARNING - 预警触发: 知识库命中率较低: 0.00 (阈值: 0.5)
|
||||
2025-09-10 22:36:53,553 - src.analytics.monitor_service - INFO - 发送通知: {'level': '警告', 'message': '知识库命中率较低: 0.00 (阈值: 0.5)', 'timestamp': '2025-09-10T22:36:53.530414', 'rule_name': '知识库命中率预警'}
|
||||
2025-09-10 22:36:53,553 - src.analytics.monitor_service - WARNING - 警告预警: 知识库命中率较低: 0.00 (阈值: 0.5)
|
||||
2025-09-10 22:36:53,553 - src.analytics.monitor_service - WARNING - 预警触发: 系统内存使用率过高: 84.1% (阈值: 80.0%)
|
||||
2025-09-10 22:36:53,553 - src.analytics.monitor_service - INFO - 发送通知: {'level': '警告', 'message': '系统内存使用率过高: 84.1% (阈值: 80.0%)', 'timestamp': '2025-09-10T22:36:53.547594', 'rule_name': '内存使用预警'}
|
||||
2025-09-10 22:36:53,553 - src.analytics.monitor_service - WARNING - 警告预警: 系统内存使用率过高: 84.1% (阈值: 80.0%)
|
||||
2025-09-10 22:36:53,883 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:36:53] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:36:54,183 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:36:54] "GET /api/agent/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:36:56,413 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:36:56] "POST /api/agent/intelligent-analysis HTTP/1.1" 200 -
|
||||
2025-09-10 22:36:56,674 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:36:56] "POST /api/agent/intelligent-analysis HTTP/1.1" 200 -
|
||||
2025-09-10 22:36:57,922 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:36:57] "GET /api/settings HTTP/1.1" 200 -
|
||||
2025-09-10 22:36:59,189 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:36:59] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:37:01,829 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:37:01] "GET /api/analytics HTTP/1.1" 200 -
|
||||
2025-09-10 22:37:04,190 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:37:04] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:37:06,201 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:37:06] "GET /api/workorders HTTP/1.1" 200 -
|
||||
2025-09-10 22:37:09,191 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:37:09] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:37:13,890 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:37:13] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:37:19,202 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:37:19] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:37:24,094 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:37:24] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:37:29,212 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:37:29] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:37:33,893 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:37:33] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:37:39,396 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:37:39] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:37:44,082 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:37:44] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:37:49,393 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:37:49] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:37:54,090 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:37:54] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:37:59,400 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:37:59] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:38:00,132 - websockets.server - INFO - connection rejected (426 Upgrade Required)
|
||||
2025-09-10 22:38:00,134 - websockets.server - INFO - connection closed
|
||||
2025-09-10 22:38:00,275 - websockets.server - INFO - connection rejected (426 Upgrade Required)
|
||||
2025-09-10 22:38:00,278 - websockets.server - INFO - connection closed
|
||||
2025-09-10 22:38:04,090 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:38:04] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:38:09,402 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:38:09] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:38:14,090 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:38:14] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:38:19,407 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:38:19] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:38:24,096 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:38:24] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:38:29,408 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:38:29] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:38:34,088 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:38:34] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:38:39,208 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:38:39] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:38:44,132 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:38:44] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:38:49,414 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:38:49] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:38:54,096 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:38:54] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:38:59,406 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:38:59] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:39:04,090 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:39:04] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:39:09,415 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:39:09] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:39:14,092 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:39:14] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:39:19,399 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:39:19] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:39:24,094 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:39:24] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:39:29,416 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:39:29] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:39:34,095 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:39:34] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:39:39,412 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:39:39] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:40:00,101 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:40:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:40:15,161 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:40:15] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:40:16,829 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:40:16] "GET /api/agent/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:40:18,698 - src.dialogue.realtime_chat - INFO - 创建新会话: session_user_001_1757515218
|
||||
2025-09-10 22:40:18,701 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:40:18] "POST /api/chat/session HTTP/1.1" 200 -
|
||||
2025-09-10 22:40:18,978 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:40:18] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:40:23,139 - src.core.llm_client - INFO - API请求成功
|
||||
2025-09-10 22:40:23,153 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:40:23] "POST /api/chat/message HTTP/1.1" 200 -
|
||||
2025-09-10 22:40:24,227 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:40:24] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:40:27,306 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:40:27] "GET /chat HTTP/1.1" 200 -
|
||||
2025-09-10 22:40:27,662 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:40:27] "[36mGET /static/js/chat.js HTTP/1.1[0m" 304 -
|
||||
2025-09-10 22:40:28,607 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:40:28] "GET /chat HTTP/1.1" 200 -
|
||||
2025-09-10 22:40:28,707 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:40:28] "[36mGET /static/js/chat.js HTTP/1.1[0m" 304 -
|
||||
2025-09-10 22:40:29,107 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:40:29] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:40:29,939 - websockets.server - INFO - connection open
|
||||
2025-09-10 22:40:29,940 - src.web.websocket_server - INFO - 客户端连接: ('::1', 13772, 0, 0)
|
||||
2025-09-10 22:40:29,950 - src.dialogue.realtime_chat - INFO - 创建新会话: session_user_001_1757515229
|
||||
2025-09-10 22:40:34,452 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:40:34] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:40:36,817 - src.core.llm_client - INFO - API请求成功
|
||||
2025-09-10 22:40:39,107 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:40:39] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:40:44,499 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:40:44] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:40:49,125 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:40:49] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:40:53,654 - src.analytics.monitor_service - INFO - 触发 1 个预警
|
||||
2025-09-10 22:40:53,654 - src.analytics.monitor_service - WARNING - 预警触发: 用户对话中断率过高: 0.50 (阈值: 0.3)
|
||||
2025-09-10 22:40:53,655 - src.analytics.monitor_service - INFO - 发送通知: {'level': '警告', 'message': '用户对话中断率过高: 0.50 (阈值: 0.3)', 'timestamp': '2025-09-10T22:40:53.647669', 'rule_name': '对话中断预警'}
|
||||
2025-09-10 22:40:53,655 - src.analytics.monitor_service - WARNING - 警告预警: 用户对话中断率过高: 0.50 (阈值: 0.3)
|
||||
2025-09-10 22:40:54,415 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:40:54] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:40:59,100 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:40:59] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:41:04,419 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:41:04] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:41:09,114 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:41:09] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:41:14,426 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:41:14] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:41:19,097 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:41:19] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:41:24,420 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:41:24] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:41:24,657 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:41:24] "GET / HTTP/1.1" 200 -
|
||||
2025-09-10 22:41:24,820 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:41:24] "[36mGET /static/js/dashboard.js HTTP/1.1[0m" 304 -
|
||||
2025-09-10 22:41:25,212 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:41:25] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:41:25,489 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:41:25] "GET /api/chat/sessions HTTP/1.1" 200 -
|
||||
2025-09-10 22:41:25,496 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:41:25] "GET /api/workorders HTTP/1.1" 200 -
|
||||
2025-09-10 22:41:25,514 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:41:25] "GET /api/system/info HTTP/1.1" 200 -
|
||||
2025-09-10 22:41:25,525 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:41:25] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 22:41:25,544 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:41:25] "GET /api/knowledge/stats HTTP/1.1" 200 -
|
||||
2025-09-10 22:41:27,055 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:41:27] "GET /api/knowledge?page=1&per_page=10 HTTP/1.1" 200 -
|
||||
2025-09-10 22:41:27,845 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:41:27] "GET /api/workorders HTTP/1.1" 200 -
|
||||
2025-09-10 22:41:30,494 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:41:30] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:41:30,803 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:41:30] "GET /api/workorders HTTP/1.1" 200 -
|
||||
2025-09-10 22:41:33,174 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:41:33] "GET /api/workorders HTTP/1.1" 200 -
|
||||
2025-09-10 22:41:35,180 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:41:35] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:41:36,624 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:41:36] "GET /api/workorders?status=open HTTP/1.1" 200 -
|
||||
2025-09-10 22:41:40,186 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:41:40] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:41:40,467 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:41:40] "GET /api/workorders?status=open HTTP/1.1" 200 -
|
||||
2025-09-10 22:41:46,429 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:41:46] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:41:51,114 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:41:51] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:41:53,547 - src.agent.auto_monitor - INFO - 执行第 2 次自动监控检查
|
||||
2025-09-10 22:41:53,562 - src.agent.auto_monitor - INFO - 触发主动行动: alert_overflow - 活跃预警数量过多: 23
|
||||
2025-09-10 22:41:53,563 - src.agent.auto_monitor - INFO - 主动行动记录: {"timestamp": "2025-09-10T22:41:53.563228", "action_type": "alert_overflow", "priority": "high", "description": "活跃预警数量过多: 23", "action": "建议立即处理预警", "data": {"alert_count": 23}}
|
||||
2025-09-10 22:41:53,563 - src.agent.auto_monitor - INFO - 处理预警溢出
|
||||
2025-09-10 22:41:53,563 - src.agent.auto_monitor - ERROR - 检查工单积压失败: 'TSPAgentAssistant' object has no attribute 'get_workorders'
|
||||
2025-09-10 22:41:56,425 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:41:56] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:00,154 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:01,436 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:01] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:03,671 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:03] "GET /alerts HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:04,020 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:04] "GET /static/css/style.css HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:04,268 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:04] "GET /static/js/app.js HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:04,686 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:04] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:04,694 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:04] "GET /api/rules HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:04,708 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:04] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:04,778 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:04] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:05,290 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:05] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:09,677 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:09] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:09,698 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:09] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:11,120 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:11] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:14,696 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:14] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:14,702 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:14] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:14,704 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:14] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:16,132 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:16] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:18,012 - src.analytics.monitor_service - INFO - 监控服务已启动
|
||||
2025-09-10 22:42:18,014 - src.main - INFO - 监控服务已启动
|
||||
2025-09-10 22:42:18,015 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:18] "POST /api/monitor/start HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:18,120 - src.analytics.monitor_service - INFO - 触发 4 个预警
|
||||
2025-09-10 22:42:18,120 - src.analytics.monitor_service - WARNING - 预警触发: 用户满意度较低: 0.00 (阈值: 0.6)
|
||||
2025-09-10 22:42:18,120 - src.analytics.monitor_service - INFO - 发送通知: {'level': '警告', 'message': '用户满意度较低: 0.00 (阈值: 0.6)', 'timestamp': '2025-09-10T22:42:18.022114', 'rule_name': '满意度预警'}
|
||||
2025-09-10 22:42:18,120 - src.analytics.monitor_service - WARNING - 警告预警: 用户满意度较低: 0.00 (阈值: 0.6)
|
||||
2025-09-10 22:42:18,121 - src.analytics.monitor_service - WARNING - 预警触发: 知识库命中率较低: 0.00 (阈值: 0.5)
|
||||
2025-09-10 22:42:18,122 - src.analytics.monitor_service - INFO - 发送通知: {'level': '警告', 'message': '知识库命中率较低: 0.00 (阈值: 0.5)', 'timestamp': '2025-09-10T22:42:18.067562', 'rule_name': '知识库命中率预警'}
|
||||
2025-09-10 22:42:18,123 - src.analytics.monitor_service - WARNING - 警告预警: 知识库命中率较低: 0.00 (阈值: 0.5)
|
||||
2025-09-10 22:42:18,124 - src.analytics.monitor_service - WARNING - 预警触发: 系统内存使用率过高: 84.8% (阈值: 80.0%)
|
||||
2025-09-10 22:42:18,126 - src.analytics.monitor_service - INFO - 发送通知: {'level': '警告', 'message': '系统内存使用率过高: 84.8% (阈值: 80.0%)', 'timestamp': '2025-09-10T22:42:18.101003', 'rule_name': '内存使用预警'}
|
||||
2025-09-10 22:42:18,126 - src.analytics.monitor_service - WARNING - 警告预警: 系统内存使用率过高: 84.8% (阈值: 80.0%)
|
||||
2025-09-10 22:42:18,126 - src.analytics.monitor_service - WARNING - 预警触发: 用户对话中断率过高: 0.50 (阈值: 0.3)
|
||||
2025-09-10 22:42:18,127 - src.analytics.monitor_service - INFO - 发送通知: {'level': '警告', 'message': '用户对话中断率过高: 0.50 (阈值: 0.3)', 'timestamp': '2025-09-10T22:42:18.113652', 'rule_name': '对话中断预警'}
|
||||
2025-09-10 22:42:18,128 - src.analytics.monitor_service - WARNING - 警告预警: 用户对话中断率过高: 0.50 (阈值: 0.3)
|
||||
2025-09-10 22:42:18,301 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:18] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:19,365 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:19] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:19,707 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:19] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:21,434 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:21] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:24,428 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:24] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:24,666 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:24] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:24,742 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:24] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:26,444 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:26] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:29,367 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:29] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:29,756 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:29] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:30,765 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:30] "POST /api/alerts/31/resolve HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:31,001 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:31] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:31,128 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:31] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:34,349 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:34] "POST /api/alerts/33/resolve HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:34,620 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:34] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:34,655 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:34] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:34,680 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:34] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:34,698 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:34] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:35,190 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:35] "POST /api/alerts/34/resolve HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:35,444 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:35] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:36,175 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:36] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:38,558 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:38] "POST /api/alerts/32/resolve HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:38,807 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:38] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:39,363 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:39] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:39,782 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:39] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:41,434 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:41] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:44,345 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:44] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:44,694 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:44] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:44,728 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:44] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:50,442 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:50] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:50,444 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:50] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:55,110 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:55] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:55,424 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:55] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 22:42:55,445 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:42:55] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:00,459 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:00,465 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:00] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:00,704 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:00,816 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:05,135 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:05] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:05,468 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:05] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:05,781 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:05] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:05,831 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:05] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:06,519 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:06] "GET /api/workorders?status=open HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:08,243 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:08] "GET / HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:08,556 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:08] "GET /static/js/dashboard.js HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:09,054 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:09] "GET /api/chat/sessions HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:09,074 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:09] "GET /api/workorders HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:09,082 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:09] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:09,107 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:09] "GET /api/system/info HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:09,177 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:09] "GET /api/knowledge/stats HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:09,183 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:09] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:09,395 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:09] "GET /api/workorders HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:10,471 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:10] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:10,486 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:10] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:13,766 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:13] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:14,401 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:14] "GET /api/workorders HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:15,159 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:15] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:15,417 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:15] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:15,444 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:15] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:19,414 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:19] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:19,860 - src.dialogue.realtime_chat - INFO - 结束会话: session_user_001_1757515229
|
||||
2025-09-10 22:43:20,114 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:20] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:20,429 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:20] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:24,414 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:24] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:25,116 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:25] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:25,429 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:25] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:25,509 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:25] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:28,069 - src.web.websocket_server - INFO - 客户端断开: ('::1', 13772, 0, 0)
|
||||
2025-09-10 22:43:28,069 - websockets.server - INFO - connection closed
|
||||
2025-09-10 22:43:29,200 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:29] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:29,839 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:29] "GET /api/agent/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:30,439 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:30] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:30,447 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:30] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:33,774 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:33] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:35,439 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:35] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:35,464 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:35] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:35,493 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:35] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:37,106 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:37] "POST /api/agent/intelligent-analysis HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:39,048 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:39] "GET /api/agent/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:39,055 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:39] "POST /api/agent/proactive-monitoring HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:39,102 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:39] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:40,119 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:40] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:40,439 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:40] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:42,340 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:42] "GET /api/workorders HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:43,756 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:43] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:45,311 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:45] "GET /api/workorders/1 HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:45,445 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:45] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:45,478 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:45] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:45,498 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:45] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:46,459 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:46] "GET /api/workorders/1 HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:48,756 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:48] "GET /api/workorders/1 HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:49,048 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:49] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:50,111 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:50] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:50,415 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:50] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:54,487 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:54] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:55,128 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:55] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:55,419 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:55] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:55,453 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:55] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:43:59,408 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:43:59] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:44:00,109 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:44:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:44:00,420 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:44:00] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:44:00,457 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:44:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:44:04,413 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:44:04] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:44:05,113 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:44:05] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:44:05,403 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:44:05] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 22:44:05,422 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:44:05] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:44:09,415 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:44:09] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:44:10,114 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:44:10] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:44:10,421 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:44:10] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:44:14,411 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:44:14] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:44:15,109 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:44:15] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:44:15,416 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:44:15] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 22:44:15,418 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:44:15] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:44:19,418 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:44:19] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:44:20,101 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:44:20] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:44:20,428 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:44:20] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:44:24,406 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:44:24] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:44:25,113 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:44:25] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:44:25,405 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:44:25] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 22:44:25,422 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:44:25] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:44:29,416 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:44:29] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:44:34,091 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:44:34] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:44:39,421 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:44:39] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:44:44,099 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:44:44] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:44:49,422 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:44:49] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:45:00,123 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:45:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:45:00,419 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:45:00] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 22:45:00,437 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:45:00] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:45:00,474 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:45:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:45:00,823 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:45:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:46:00,401 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:46:00] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 22:46:00,412 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:46:00] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:46:00,413 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:46:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:46:00,671 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:46:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:46:00,734 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:46:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:46:20,637 - __main__ - INFO - 正在启动TSP智能助手综合管理平台...
|
||||
2025-09-10 22:46:21,476 - src.core.database - INFO - 数据库初始化成功
|
||||
2025-09-10 22:46:22,871 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 48 个条目
|
||||
2025-09-10 22:46:22,880 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 48 个条目
|
||||
2025-09-10 22:46:22,881 - src.main - INFO - TSP助手初始化完成
|
||||
2025-09-10 22:46:22,891 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 48 个条目
|
||||
2025-09-10 22:46:22,900 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 48 个条目
|
||||
2025-09-10 22:46:22,902 - src.main - INFO - TSP助手初始化完成
|
||||
2025-09-10 22:46:22,902 - src.agent.tool_manager - INFO - 注册工具: search_knowledge
|
||||
2025-09-10 22:46:22,902 - src.agent.tool_manager - INFO - 注册工具: create_work_order
|
||||
2025-09-10 22:46:22,903 - src.agent.tool_manager - INFO - 注册工具: update_work_order
|
||||
2025-09-10 22:46:22,903 - src.agent.tool_manager - INFO - 注册工具: generate_response
|
||||
2025-09-10 22:46:22,903 - src.agent.tool_manager - INFO - 注册工具: analyze_data
|
||||
2025-09-10 22:46:22,903 - src.agent.tool_manager - INFO - 注册工具: send_notification
|
||||
2025-09-10 22:46:22,904 - src.agent.tool_manager - INFO - 注册工具: schedule_task
|
||||
2025-09-10 22:46:22,904 - src.agent.tool_manager - INFO - 注册工具: web_search
|
||||
2025-09-10 22:46:22,904 - src.agent.tool_manager - INFO - 注册工具: file_operation
|
||||
2025-09-10 22:46:22,905 - src.agent.tool_manager - INFO - 注册工具: database_query
|
||||
2025-09-10 22:46:22,905 - src.agent.tool_manager - INFO - 已注册 10 个默认工具
|
||||
2025-09-10 22:46:22,905 - src.agent.agent_core - INFO - Agent核心初始化完成
|
||||
2025-09-10 22:46:22,905 - src.agent_assistant - INFO - TSP Agent助手初始化完成
|
||||
2025-09-10 22:46:22,916 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 48 个条目
|
||||
2025-09-10 22:46:22,978 - werkzeug - INFO - [31m[1mWARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.[0m
|
||||
* Running on all addresses (0.0.0.0)
|
||||
* Running on http://127.0.0.1:5000
|
||||
* Running on http://192.168.26.238:5000
|
||||
2025-09-10 22:46:22,978 - werkzeug - INFO - [33mPress CTRL+C to quit[0m
|
||||
2025-09-10 22:46:23,004 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 48 个条目
|
||||
2025-09-10 22:46:23,006 - src.web.websocket_server - INFO - 启动WebSocket服务器: ws://localhost:8765
|
||||
2025-09-10 22:46:23,011 - websockets.server - INFO - server listening on 127.0.0.1:8765
|
||||
2025-09-10 22:46:23,011 - websockets.server - INFO - server listening on [::1]:8765
|
||||
2025-09-10 22:46:28,171 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:46:28] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:46:28,747 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:46:28] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:46:34,394 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:46:34] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:46:35,437 - websockets.server - INFO - connection rejected (200 OK)
|
||||
2025-09-10 22:46:35,438 - websockets.server - INFO - connection closed
|
||||
2025-09-10 22:46:35,608 - websockets.server - INFO - connection rejected (200 OK)
|
||||
2025-09-10 22:46:35,624 - websockets.server - INFO - connection closed
|
||||
2025-09-10 22:46:39,083 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:46:39] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:46:44,408 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:46:44] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:46:46,320 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:46:46] "GET / HTTP/1.1" 200 -
|
||||
2025-09-10 22:46:46,613 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:46:46] "GET /static/js/dashboard.js HTTP/1.1" 200 -
|
||||
2025-09-10 22:46:47,410 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:46:47] "GET /api/chat/sessions HTTP/1.1" 200 -
|
||||
2025-09-10 22:46:47,417 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:46:47] "GET /api/workorders HTTP/1.1" 200 -
|
||||
2025-09-10 22:46:47,420 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:46:47] "GET /api/system/info HTTP/1.1" 200 -
|
||||
2025-09-10 22:46:47,456 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:46:47] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 22:46:47,466 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:46:47] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:46:47,477 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:46:47] "GET /api/knowledge/stats HTTP/1.1" 200 -
|
||||
2025-09-10 22:46:47,539 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:46:47] "[33mGET /favicon.ico HTTP/1.1[0m" 404 -
|
||||
2025-09-10 22:46:49,088 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:46:49] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:46:52,419 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:46:52] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:46:54,406 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:46:54] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:46:55,108 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:46:55] "GET /api/workorders HTTP/1.1" 200 -
|
||||
2025-09-10 22:46:56,537 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:46:56] "GET /api/workorders/1 HTTP/1.1" 200 -
|
||||
2025-09-10 22:46:57,437 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:46:57] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:46:59,087 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:46:59] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:47:00,403 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:47:00] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 22:47:00,432 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:47:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:47:00,437 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:47:00] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:47:00,655 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:47:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:47:02,410 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:47:02] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:47:04,092 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:47:04] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:47:06,352 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:47:06] "GET /api/workorders HTTP/1.1" 200 -
|
||||
2025-09-10 22:47:07,413 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:47:07] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:47:09,004 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:47:09] "GET /api/knowledge?page=1&per_page=10 HTTP/1.1" 200 -
|
||||
2025-09-10 22:47:09,389 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:47:09] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:47:12,411 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:47:12] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:47:13,324 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:47:13] "GET /api/workorders HTTP/1.1" 200 -
|
||||
2025-09-10 22:47:14,093 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:47:14] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:47:16,978 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:47:16] "GET /api/knowledge?page=1&per_page=10 HTTP/1.1" 200 -
|
||||
2025-09-10 22:47:17,417 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:47:17] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:47:17,776 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:47:17] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 22:47:18,450 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:47:18] "GET /api/knowledge?page=1&per_page=10 HTTP/1.1" 200 -
|
||||
2025-09-10 22:47:19,406 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:47:19] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:47:21,975 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:47:21] "GET /api/agent/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:47:22,412 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:47:22] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:47:24,097 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:47:24] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:47:24,696 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:47:24] "GET /api/chat/sessions HTTP/1.1" 200 -
|
||||
2025-09-10 22:47:24,702 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:47:24] "GET /api/workorders HTTP/1.1" 200 -
|
||||
2025-09-10 22:47:24,709 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:47:24] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 22:47:24,723 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:47:24] "GET /api/knowledge/stats HTTP/1.1" 200 -
|
||||
2025-09-10 22:47:25,262 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:47:25] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 22:47:25,706 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:47:25] "GET /api/workorders HTTP/1.1" 200 -
|
||||
2025-09-10 22:47:26,507 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:47:26] "GET /api/analytics HTTP/1.1" 200 -
|
||||
2025-09-10 22:47:27,043 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:47:27] "GET /api/settings HTTP/1.1" 200 -
|
||||
2025-09-10 22:47:27,415 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:47:27] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:47:29,439 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:47:29] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:47:33,085 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:47:33] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:47:38,088 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:47:38] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:47:43,094 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:47:43] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:47:48,086 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:47:48] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:47:53,083 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:47:53] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:47:58,090 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:47:58] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:48:00,097 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:48:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:48:00,388 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:48:00] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 22:48:00,399 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:48:00] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:48:00,415 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:48:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:48:00,736 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:48:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:48:03,102 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:48:03] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:48:08,096 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:48:08] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:48:13,093 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:48:13] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:48:18,095 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:48:18] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:48:23,102 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:48:23] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:48:28,106 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:48:28] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:49:00,160 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:49:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:49:00,452 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:49:00] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 22:49:00,454 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:49:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:49:00,477 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:49:00] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:49:00,692 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:49:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:49:00,798 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:49:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:50:00,136 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:50:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:50:00,143 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:50:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:50:00,413 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:50:00] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 22:50:00,442 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:50:00] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:50:00,477 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:50:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:50:00,834 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:50:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:51:00,112 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:51:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:51:00,432 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:51:00] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 22:51:00,455 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:51:00] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:51:00,458 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:51:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:51:00,675 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:51:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:51:00,800 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:51:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:52:00,123 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:52:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:52:00,125 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:52:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:52:00,410 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:52:00] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 22:52:00,426 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:52:00] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:52:00,453 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:52:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:52:00,784 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:52:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:52:24,642 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:52:24] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:52:25,904 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:52:25] "GET /api/analytics HTTP/1.1" 200 -
|
||||
2025-09-10 22:52:27,456 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:52:27] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:52:33,108 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:52:33] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:52:38,104 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:52:38] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:52:43,103 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:52:43] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:52:48,102 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:52:48] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:52:53,106 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:52:53] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:52:58,092 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:52:58] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:53:00,415 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:53:00] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 22:53:00,442 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:53:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:53:00,445 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:53:00] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:53:00,684 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:53:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:53:00,772 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:53:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:53:03,104 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:53:03] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:53:08,108 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:53:08] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:53:13,096 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:53:13] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:53:18,104 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:53:18] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:53:23,095 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:53:23] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:53:28,116 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:53:28] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:54:00,125 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:54:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:54:00,146 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:54:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:54:00,435 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:54:00] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 22:54:00,474 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:54:00] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:54:00,488 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:54:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:54:00,829 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:54:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:55:00,142 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:55:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:55:00,443 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:55:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:55:00,455 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:55:00] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 22:55:00,474 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:55:00] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:55:00,719 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:55:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:55:00,782 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:55:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:55:48,827 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:55:48] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:55:53,096 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:55:53] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:55:58,093 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:55:58] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:56:00,098 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:56:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:56:00,400 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:56:00] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 22:56:00,413 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:56:00] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:56:00,424 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:56:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:56:00,753 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:56:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:56:03,091 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:56:03] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:56:08,102 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:56:08] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:56:13,088 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:56:13] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:56:18,095 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:56:18] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:56:23,098 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:56:23] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:56:28,099 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:56:28] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:56:33,088 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:56:33] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:56:38,090 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:56:38] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:56:43,089 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:56:43] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:56:48,095 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:56:48] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:57:00,107 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:57:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:57:00,425 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:57:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:57:00,437 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:57:00] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 22:57:00,463 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:57:00] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:57:00,684 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:57:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:57:00,770 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:57:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:58:03,303 - __main__ - INFO - 正在启动TSP智能助手综合管理平台...
|
||||
2025-09-10 22:58:05,745 - src.core.database - INFO - 数据库初始化成功
|
||||
2025-09-10 22:58:07,461 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 48 个条目
|
||||
2025-09-10 22:58:07,470 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 48 个条目
|
||||
2025-09-10 22:58:07,471 - src.main - INFO - TSP助手初始化完成
|
||||
2025-09-10 22:58:07,480 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 48 个条目
|
||||
2025-09-10 22:58:07,492 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 48 个条目
|
||||
2025-09-10 22:58:07,494 - src.main - INFO - TSP助手初始化完成
|
||||
2025-09-10 22:58:07,494 - src.agent.tool_manager - INFO - 注册工具: search_knowledge
|
||||
2025-09-10 22:58:07,495 - src.agent.tool_manager - INFO - 注册工具: create_work_order
|
||||
2025-09-10 22:58:07,495 - src.agent.tool_manager - INFO - 注册工具: update_work_order
|
||||
2025-09-10 22:58:07,495 - src.agent.tool_manager - INFO - 注册工具: generate_response
|
||||
2025-09-10 22:58:07,495 - src.agent.tool_manager - INFO - 注册工具: analyze_data
|
||||
2025-09-10 22:58:07,495 - src.agent.tool_manager - INFO - 注册工具: send_notification
|
||||
2025-09-10 22:58:07,495 - src.agent.tool_manager - INFO - 注册工具: schedule_task
|
||||
2025-09-10 22:58:07,495 - src.agent.tool_manager - INFO - 注册工具: web_search
|
||||
2025-09-10 22:58:07,496 - src.agent.tool_manager - INFO - 注册工具: file_operation
|
||||
2025-09-10 22:58:07,496 - src.agent.tool_manager - INFO - 注册工具: database_query
|
||||
2025-09-10 22:58:07,496 - src.agent.tool_manager - INFO - 已注册 10 个默认工具
|
||||
2025-09-10 22:58:07,496 - src.agent.agent_core - INFO - Agent核心初始化完成
|
||||
2025-09-10 22:58:07,496 - src.agent_assistant - INFO - TSP Agent助手初始化完成
|
||||
2025-09-10 22:58:07,507 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 48 个条目
|
||||
2025-09-10 22:58:07,570 - werkzeug - INFO - [31m[1mWARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.[0m
|
||||
* Running on all addresses (0.0.0.0)
|
||||
* Running on http://127.0.0.1:5000
|
||||
* Running on http://192.168.26.238:5000
|
||||
2025-09-10 22:58:07,571 - werkzeug - INFO - [33mPress CTRL+C to quit[0m
|
||||
2025-09-10 22:58:07,597 - src.knowledge_base.knowledge_manager - INFO - 向量化器加载成功,包含 48 个条目
|
||||
2025-09-10 22:58:07,599 - src.web.websocket_server - INFO - 启动WebSocket服务器: ws://localhost:8765
|
||||
2025-09-10 22:58:07,603 - websockets.server - INFO - server listening on 127.0.0.1:8765
|
||||
2025-09-10 22:58:07,604 - websockets.server - INFO - server listening on [::1]:8765
|
||||
2025-09-10 22:58:20,916 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:58:20] "GET / HTTP/1.1" 200 -
|
||||
2025-09-10 22:58:21,166 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:58:21] "GET /static/js/dashboard.js HTTP/1.1" 200 -
|
||||
2025-09-10 22:58:21,410 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:58:21] "GET /api/chat/sessions HTTP/1.1" 200 -
|
||||
2025-09-10 22:58:21,417 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:58:21] "GET /api/workorders HTTP/1.1" 200 -
|
||||
2025-09-10 22:58:21,439 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:58:21] "GET /api/system/info HTTP/1.1" 200 -
|
||||
2025-09-10 22:58:21,463 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:58:21] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 22:58:21,495 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:58:21] "GET /api/knowledge/stats HTTP/1.1" 200 -
|
||||
2025-09-10 22:58:21,520 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:58:21] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:58:21,608 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:58:21] "GET /api/analytics HTTP/1.1" 200 -
|
||||
2025-09-10 22:58:22,927 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:58:22] "GET /api/workorders HTTP/1.1" 200 -
|
||||
2025-09-10 22:58:26,415 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:58:26] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:58:29,362 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:58:29] "GET /api/workorders/import/template HTTP/1.1" 200 -
|
||||
2025-09-10 22:58:29,371 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:58:29] "[33mGET /uploads/workorder_template.xlsx HTTP/1.1[0m" 404 -
|
||||
2025-09-10 22:58:31,416 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:58:31] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:58:32,421 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:58:32] "[33mGET /uploads/workorder_template.xlsx HTTP/1.1[0m" 404 -
|
||||
2025-09-10 22:58:36,414 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:58:36] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:58:41,419 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:58:41] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:58:46,421 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:58:46] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:58:51,415 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:58:51] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:58:55,684 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:58:55] "[31m[1mPOST /api/workorders/import HTTP/1.1[0m" 400 -
|
||||
2025-09-10 22:58:56,415 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:58:56] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:59:00,120 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:59:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:59:00,121 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:59:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:59:00,402 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:59:00] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 22:59:00,417 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:59:00] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 22:59:00,442 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:59:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:59:00,772 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:59:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:59:01,512 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:59:01] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:59:07,096 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:59:07] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:59:12,110 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:59:12] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:59:17,088 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:59:17] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:59:22,098 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:59:22] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:59:27,119 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:59:27] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:59:32,117 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:59:32] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:59:37,121 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:59:37] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:59:42,099 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:59:42] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:59:47,104 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:59:47] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:59:52,107 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:59:52] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 22:59:57,109 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 22:59:57] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 23:00:00,130 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:00:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 23:00:00,429 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:00:00] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 23:00:00,458 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:00:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 23:00:00,462 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:00:00] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 23:00:00,690 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:00:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 23:00:00,797 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:00:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 23:00:02,113 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:00:02] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 23:01:00,135 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:01:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 23:01:00,183 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:01:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 23:01:00,469 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:01:00] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 23:01:00,471 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:01:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 23:01:00,480 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:01:00] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 23:01:00,708 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:01:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 23:01:00,819 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:01:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 23:02:00,134 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:02:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 23:02:00,142 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:02:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 23:02:00,184 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:02:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 23:02:00,413 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:02:00] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 23:02:00,440 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:02:00] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 23:02:00,475 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:02:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 23:02:00,809 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:02:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 23:03:00,120 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:03:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 23:03:00,161 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:03:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 23:03:00,427 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:03:00] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 23:03:00,467 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:03:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 23:03:00,473 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:03:00] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 23:03:00,683 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:03:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 23:03:00,811 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:03:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 23:04:00,125 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:04:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 23:04:00,144 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:04:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 23:04:00,189 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:04:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 23:04:00,428 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:04:00] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 23:04:00,446 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:04:00] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 23:04:00,469 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:04:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 23:04:00,800 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:04:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 23:05:00,134 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:05:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 23:05:00,177 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:05:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 23:05:00,429 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:05:00] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 23:05:00,462 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:05:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 23:05:00,472 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:05:00] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 23:05:00,701 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:05:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 23:05:00,806 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:05:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 23:06:00,145 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:06:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 23:06:00,157 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:06:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 23:06:00,201 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:06:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 23:06:00,417 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:06:00] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 23:06:00,442 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:06:00] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 23:06:00,497 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:06:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 23:06:00,828 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:06:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 23:07:00,131 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:07:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 23:07:00,176 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:07:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 23:07:00,426 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:07:00] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 23:07:00,452 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:07:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 23:07:00,458 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:07:00] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 23:07:00,681 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:07:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 23:07:00,793 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:07:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 23:08:00,141 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:08:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 23:08:00,143 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:08:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 23:08:00,196 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:08:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 23:08:00,436 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:08:00] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 23:08:00,455 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:08:00] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 23:08:00,496 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:08:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 23:08:00,849 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:08:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 23:09:00,123 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:09:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 23:09:00,160 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:09:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 23:09:00,425 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:09:00] "GET /api/alerts HTTP/1.1" 200 -
|
||||
2025-09-10 23:09:00,446 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:09:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 23:09:00,448 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:09:00] "GET /api/monitor/status HTTP/1.1" 200 -
|
||||
2025-09-10 23:09:00,700 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:09:00] "GET /api/health HTTP/1.1" 200 -
|
||||
2025-09-10 23:09:00,781 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:09:00] "GET /api/health HTTP/1.1" 200 -
|
||||
|
||||
@@ -19,6 +19,7 @@ psutil>=5.9.0
|
||||
|
||||
# 数据处理
|
||||
pandas>=2.0.0
|
||||
openpyxl>=3.1.0
|
||||
|
||||
# 向量化
|
||||
sentence-transformers>=2.2.0
|
||||
|
||||
Binary file not shown.
BIN
src/agent/__pycache__/auto_monitor.cpython-311.pyc
Normal file
BIN
src/agent/__pycache__/auto_monitor.cpython-311.pyc
Normal file
Binary file not shown.
358
src/agent/auto_monitor.py
Normal file
358
src/agent/auto_monitor.py
Normal file
@@ -0,0 +1,358 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
自动监控服务
|
||||
实现Agent的主动调用功能
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
import threading
|
||||
import time
|
||||
from datetime import datetime, timedelta
|
||||
from typing import Dict, Any, List, Optional
|
||||
import json
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class AutoMonitorService:
|
||||
"""自动监控服务"""
|
||||
|
||||
def __init__(self, agent_assistant):
|
||||
self.agent_assistant = agent_assistant
|
||||
self.is_running = False
|
||||
self.monitor_thread = None
|
||||
self.check_interval = 300 # 5分钟检查一次
|
||||
self.last_check_time = None
|
||||
self.monitoring_stats = {
|
||||
"total_checks": 0,
|
||||
"proactive_actions": 0,
|
||||
"last_action_time": None,
|
||||
"error_count": 0
|
||||
}
|
||||
|
||||
def start_auto_monitoring(self) -> bool:
|
||||
"""启动自动监控"""
|
||||
try:
|
||||
if self.is_running:
|
||||
logger.warning("自动监控已在运行中")
|
||||
return True
|
||||
|
||||
self.is_running = True
|
||||
self.monitor_thread = threading.Thread(target=self._monitoring_loop, daemon=True)
|
||||
self.monitor_thread.start()
|
||||
|
||||
logger.info("自动监控服务已启动")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"启动自动监控失败: {e}")
|
||||
return False
|
||||
|
||||
def stop_auto_monitoring(self) -> bool:
|
||||
"""停止自动监控"""
|
||||
try:
|
||||
self.is_running = False
|
||||
if self.monitor_thread and self.monitor_thread.is_alive():
|
||||
self.monitor_thread.join(timeout=5)
|
||||
|
||||
logger.info("自动监控服务已停止")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"停止自动监控失败: {e}")
|
||||
return False
|
||||
|
||||
def _monitoring_loop(self):
|
||||
"""监控循环"""
|
||||
logger.info("自动监控循环已启动")
|
||||
|
||||
while self.is_running:
|
||||
try:
|
||||
# 执行监控检查
|
||||
self._perform_monitoring_check()
|
||||
|
||||
# 等待下次检查
|
||||
time.sleep(self.check_interval)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"监控循环错误: {e}")
|
||||
self.monitoring_stats["error_count"] += 1
|
||||
time.sleep(60) # 出错后等待1分钟
|
||||
|
||||
def _perform_monitoring_check(self):
|
||||
"""执行监控检查"""
|
||||
try:
|
||||
self.monitoring_stats["total_checks"] += 1
|
||||
self.last_check_time = datetime.now()
|
||||
|
||||
logger.info(f"执行第 {self.monitoring_stats['total_checks']} 次自动监控检查")
|
||||
|
||||
# 1. 检查系统健康状态
|
||||
self._check_system_health()
|
||||
|
||||
# 2. 检查预警状态
|
||||
self._check_alert_status()
|
||||
|
||||
# 3. 检查工单积压
|
||||
self._check_workorder_backlog()
|
||||
|
||||
# 4. 检查知识库质量
|
||||
self._check_knowledge_quality()
|
||||
|
||||
# 5. 检查用户满意度
|
||||
self._check_user_satisfaction()
|
||||
|
||||
# 6. 检查系统性能
|
||||
self._check_system_performance()
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"执行监控检查失败: {e}")
|
||||
self.monitoring_stats["error_count"] += 1
|
||||
|
||||
def _check_system_health(self):
|
||||
"""检查系统健康状态"""
|
||||
try:
|
||||
health = self.agent_assistant.get_system_health()
|
||||
health_score = health.get("health_score", 1.0)
|
||||
|
||||
if health_score < 0.7:
|
||||
self._trigger_proactive_action({
|
||||
"type": "system_health_warning",
|
||||
"priority": "high",
|
||||
"description": f"系统健康分数较低: {health_score:.2f}",
|
||||
"action": "建议立即检查系统状态",
|
||||
"data": health
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"检查系统健康状态失败: {e}")
|
||||
|
||||
def _check_alert_status(self):
|
||||
"""检查预警状态"""
|
||||
try:
|
||||
alerts = self.agent_assistant.get_active_alerts()
|
||||
alert_count = len(alerts) if isinstance(alerts, list) else 0
|
||||
|
||||
if alert_count > 5:
|
||||
self._trigger_proactive_action({
|
||||
"type": "alert_overflow",
|
||||
"priority": "high",
|
||||
"description": f"活跃预警数量过多: {alert_count}",
|
||||
"action": "建议立即处理预警",
|
||||
"data": {"alert_count": alert_count}
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"检查预警状态失败: {e}")
|
||||
|
||||
def _check_workorder_backlog(self):
|
||||
"""检查工单积压"""
|
||||
try:
|
||||
# 获取工单统计
|
||||
workorders = self.agent_assistant.get_workorders()
|
||||
if isinstance(workorders, list):
|
||||
open_count = len([w for w in workorders if w.get("status") == "open"])
|
||||
in_progress_count = len([w for w in workorders if w.get("status") == "in_progress"])
|
||||
total_pending = open_count + in_progress_count
|
||||
|
||||
if total_pending > 10:
|
||||
self._trigger_proactive_action({
|
||||
"type": "workorder_backlog",
|
||||
"priority": "medium",
|
||||
"description": f"待处理工单过多: {total_pending}",
|
||||
"action": "建议增加处理人员或优化流程",
|
||||
"data": {
|
||||
"open_count": open_count,
|
||||
"in_progress_count": in_progress_count,
|
||||
"total_pending": total_pending
|
||||
}
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"检查工单积压失败: {e}")
|
||||
|
||||
def _check_knowledge_quality(self):
|
||||
"""检查知识库质量"""
|
||||
try:
|
||||
stats = self.agent_assistant.knowledge_manager.get_knowledge_stats()
|
||||
avg_confidence = stats.get("average_confidence", 0.8)
|
||||
total_entries = stats.get("total_entries", 0)
|
||||
|
||||
if avg_confidence < 0.6:
|
||||
self._trigger_proactive_action({
|
||||
"type": "knowledge_quality_low",
|
||||
"priority": "medium",
|
||||
"description": f"知识库平均置信度较低: {avg_confidence:.2f}",
|
||||
"action": "建议更新和优化知识库内容",
|
||||
"data": {"avg_confidence": avg_confidence, "total_entries": total_entries}
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"检查知识库质量失败: {e}")
|
||||
|
||||
def _check_user_satisfaction(self):
|
||||
"""检查用户满意度"""
|
||||
try:
|
||||
# 模拟检查用户满意度
|
||||
# 这里可以从数据库或API获取真实的满意度数据
|
||||
satisfaction_score = 0.75 # 模拟数据
|
||||
|
||||
if satisfaction_score < 0.7:
|
||||
self._trigger_proactive_action({
|
||||
"type": "low_satisfaction",
|
||||
"priority": "high",
|
||||
"description": f"用户满意度较低: {satisfaction_score:.2f}",
|
||||
"action": "建议分析低满意度原因并改进服务",
|
||||
"data": {"satisfaction_score": satisfaction_score}
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"检查用户满意度失败: {e}")
|
||||
|
||||
def _check_system_performance(self):
|
||||
"""检查系统性能"""
|
||||
try:
|
||||
# 模拟检查系统性能指标
|
||||
response_time = 1.2 # 模拟响应时间(秒)
|
||||
error_rate = 0.02 # 模拟错误率
|
||||
|
||||
if response_time > 2.0:
|
||||
self._trigger_proactive_action({
|
||||
"type": "slow_response",
|
||||
"priority": "medium",
|
||||
"description": f"系统响应时间过慢: {response_time:.2f}秒",
|
||||
"action": "建议优化系统性能",
|
||||
"data": {"response_time": response_time}
|
||||
})
|
||||
|
||||
if error_rate > 0.05:
|
||||
self._trigger_proactive_action({
|
||||
"type": "high_error_rate",
|
||||
"priority": "high",
|
||||
"description": f"系统错误率过高: {error_rate:.2%}",
|
||||
"action": "建议立即检查系统错误",
|
||||
"data": {"error_rate": error_rate}
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"检查系统性能失败: {e}")
|
||||
|
||||
def _trigger_proactive_action(self, action_data: Dict[str, Any]):
|
||||
"""触发主动行动"""
|
||||
try:
|
||||
self.monitoring_stats["proactive_actions"] += 1
|
||||
self.monitoring_stats["last_action_time"] = datetime.now()
|
||||
|
||||
logger.info(f"触发主动行动: {action_data['type']} - {action_data['description']}")
|
||||
|
||||
# 记录主动行动
|
||||
self._log_proactive_action(action_data)
|
||||
|
||||
# 根据行动类型执行相应操作
|
||||
self._execute_proactive_action(action_data)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"触发主动行动失败: {e}")
|
||||
|
||||
def _log_proactive_action(self, action_data: Dict[str, Any]):
|
||||
"""记录主动行动"""
|
||||
try:
|
||||
log_entry = {
|
||||
"timestamp": datetime.now().isoformat(),
|
||||
"action_type": action_data["type"],
|
||||
"priority": action_data["priority"],
|
||||
"description": action_data["description"],
|
||||
"action": action_data["action"],
|
||||
"data": action_data.get("data", {})
|
||||
}
|
||||
|
||||
# 这里可以将日志保存到数据库或文件
|
||||
logger.info(f"主动行动记录: {json.dumps(log_entry, ensure_ascii=False)}")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"记录主动行动失败: {e}")
|
||||
|
||||
def _execute_proactive_action(self, action_data: Dict[str, Any]):
|
||||
"""执行主动行动"""
|
||||
try:
|
||||
action_type = action_data["type"]
|
||||
|
||||
if action_type == "system_health_warning":
|
||||
self._handle_system_health_warning(action_data)
|
||||
elif action_type == "alert_overflow":
|
||||
self._handle_alert_overflow(action_data)
|
||||
elif action_type == "workorder_backlog":
|
||||
self._handle_workorder_backlog(action_data)
|
||||
elif action_type == "knowledge_quality_low":
|
||||
self._handle_knowledge_quality_low(action_data)
|
||||
elif action_type == "low_satisfaction":
|
||||
self._handle_low_satisfaction(action_data)
|
||||
elif action_type == "slow_response":
|
||||
self._handle_slow_response(action_data)
|
||||
elif action_type == "high_error_rate":
|
||||
self._handle_high_error_rate(action_data)
|
||||
else:
|
||||
logger.warning(f"未知的主动行动类型: {action_type}")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"执行主动行动失败: {e}")
|
||||
|
||||
def _handle_system_health_warning(self, action_data: Dict[str, Any]):
|
||||
"""处理系统健康警告"""
|
||||
logger.info("处理系统健康警告")
|
||||
# 这里可以实现具体的处理逻辑,如发送通知、重启服务等
|
||||
|
||||
def _handle_alert_overflow(self, action_data: Dict[str, Any]):
|
||||
"""处理预警溢出"""
|
||||
logger.info("处理预警溢出")
|
||||
# 这里可以实现具体的处理逻辑,如自动处理预警、发送通知等
|
||||
|
||||
def _handle_workorder_backlog(self, action_data: Dict[str, Any]):
|
||||
"""处理工单积压"""
|
||||
logger.info("处理工单积压")
|
||||
# 这里可以实现具体的处理逻辑,如自动分配工单、发送提醒等
|
||||
|
||||
def _handle_knowledge_quality_low(self, action_data: Dict[str, Any]):
|
||||
"""处理知识库质量低"""
|
||||
logger.info("处理知识库质量低")
|
||||
# 这里可以实现具体的处理逻辑,如自动更新知识库、发送提醒等
|
||||
|
||||
def _handle_low_satisfaction(self, action_data: Dict[str, Any]):
|
||||
"""处理低满意度"""
|
||||
logger.info("处理低满意度")
|
||||
# 这里可以实现具体的处理逻辑,如分析原因、发送通知等
|
||||
|
||||
def _handle_slow_response(self, action_data: Dict[str, Any]):
|
||||
"""处理响应慢"""
|
||||
logger.info("处理响应慢")
|
||||
# 这里可以实现具体的处理逻辑,如优化配置、发送通知等
|
||||
|
||||
def _handle_high_error_rate(self, action_data: Dict[str, Any]):
|
||||
"""处理高错误率"""
|
||||
logger.info("处理高错误率")
|
||||
# 这里可以实现具体的处理逻辑,如检查日志、发送通知等
|
||||
|
||||
def get_monitoring_status(self) -> Dict[str, Any]:
|
||||
"""获取监控状态"""
|
||||
return {
|
||||
"is_running": self.is_running,
|
||||
"check_interval": self.check_interval,
|
||||
"last_check_time": self.last_check_time.isoformat() if self.last_check_time else None,
|
||||
"stats": self.monitoring_stats
|
||||
}
|
||||
|
||||
def update_check_interval(self, interval: int) -> bool:
|
||||
"""更新检查间隔"""
|
||||
try:
|
||||
if interval < 60: # 最少1分钟
|
||||
logger.warning("检查间隔不能少于60秒")
|
||||
return False
|
||||
|
||||
self.check_interval = interval
|
||||
logger.info(f"检查间隔已更新为 {interval} 秒")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"更新检查间隔失败: {e}")
|
||||
return False
|
||||
@@ -13,6 +13,7 @@ import json
|
||||
|
||||
from src.main import TSPAssistant
|
||||
from src.agent import AgentCore, AgentState
|
||||
from src.agent.auto_monitor import AutoMonitorService
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -26,6 +27,9 @@ class TSPAgentAssistant(TSPAssistant):
|
||||
# 初始化Agent核心
|
||||
self.agent_core = AgentCore()
|
||||
|
||||
# 初始化自动监控服务
|
||||
self.auto_monitor = AutoMonitorService(self)
|
||||
|
||||
# Agent特有功能
|
||||
self.is_agent_mode = True
|
||||
self.proactive_tasks = []
|
||||
@@ -409,10 +413,13 @@ class TSPAgentAssistant(TSPAssistant):
|
||||
def get_agent_status(self) -> Dict[str, Any]:
|
||||
"""获取Agent状态"""
|
||||
try:
|
||||
# 获取自动监控状态
|
||||
monitor_status = self.auto_monitor.get_monitoring_status()
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"agent_mode": self.is_agent_mode,
|
||||
"monitoring_active": getattr(self, '_monitoring_active', False),
|
||||
"monitoring_active": monitor_status["is_running"],
|
||||
"status": "active" if self.is_agent_mode else "inactive",
|
||||
"active_goals": 0, # 简化处理
|
||||
"available_tools": 6, # 简化处理
|
||||
@@ -424,7 +431,8 @@ class TSPAgentAssistant(TSPAssistant):
|
||||
{"name": "analyze_data", "usage_count": 0, "success_rate": 0.8},
|
||||
{"name": "send_notification", "usage_count": 0, "success_rate": 0.8}
|
||||
],
|
||||
"execution_history": []
|
||||
"execution_history": [],
|
||||
"auto_monitor": monitor_status
|
||||
}
|
||||
except Exception as e:
|
||||
logger.error(f"获取Agent状态失败: {e}")
|
||||
@@ -456,11 +464,14 @@ class TSPAgentAssistant(TSPAssistant):
|
||||
# 启动基础监控
|
||||
self.start_monitoring()
|
||||
|
||||
# 启动Agent主动监控(同步版本)
|
||||
self._start_monitoring_loop()
|
||||
|
||||
logger.info("主动监控已启动")
|
||||
return True
|
||||
# 启动自动监控服务
|
||||
success = self.auto_monitor.start_auto_monitoring()
|
||||
if success:
|
||||
logger.info("主动监控已启动")
|
||||
return True
|
||||
else:
|
||||
logger.error("启动自动监控服务失败")
|
||||
return False
|
||||
except Exception as e:
|
||||
logger.error(f"启动主动监控失败: {e}")
|
||||
return False
|
||||
@@ -471,11 +482,14 @@ class TSPAgentAssistant(TSPAssistant):
|
||||
# 停止基础监控
|
||||
self.stop_monitoring()
|
||||
|
||||
# 停止Agent主动监控
|
||||
self._stop_monitoring_loop()
|
||||
|
||||
logger.info("主动监控已停止")
|
||||
return True
|
||||
# 停止自动监控服务
|
||||
success = self.auto_monitor.stop_auto_monitoring()
|
||||
if success:
|
||||
logger.info("主动监控已停止")
|
||||
return True
|
||||
else:
|
||||
logger.error("停止自动监控服务失败")
|
||||
return False
|
||||
except Exception as e:
|
||||
logger.error(f"停止主动监控失败: {e}")
|
||||
return False
|
||||
@@ -619,30 +633,38 @@ class TSPAgentAssistant(TSPAssistant):
|
||||
return ""
|
||||
|
||||
def _extract_knowledge_from_content(self, content: str, filename: str) -> List[Dict[str, Any]]:
|
||||
"""从内容中提取知识"""
|
||||
"""从内容中提取知识,结合工单数据优化"""
|
||||
try:
|
||||
# 构建提示词
|
||||
# 获取历史工单数据用于参考
|
||||
workorder_data = self._get_workorder_insights()
|
||||
|
||||
# 构建增强的提示词
|
||||
prompt = f"""
|
||||
请从以下文档内容中提取问答对,用于构建知识库:
|
||||
请从以下文档内容中提取问答对,用于构建知识库。请结合历史工单数据来优化提取结果:
|
||||
|
||||
文档名称:{filename}
|
||||
文档内容:
|
||||
{content[:2000]}...
|
||||
|
||||
历史工单数据参考:
|
||||
{workorder_data}
|
||||
|
||||
请按照以下格式提取问答对:
|
||||
1. 问题:具体的问题描述
|
||||
2. 答案:详细的答案内容
|
||||
1. 问题:具体的问题描述(参考工单中的常见问题)
|
||||
2. 答案:详细的答案内容(结合工单处理经验)
|
||||
3. 分类:问题所属类别(技术问题、APP功能、远程控制、车辆绑定、其他)
|
||||
4. 置信度:0-1之间的数值
|
||||
5. 工单关联:是否与历史工单相关
|
||||
|
||||
请提取3-5个最有价值的问答对,每个问答对都要完整且实用。
|
||||
请提取3-5个最有价值的问答对,优先提取与历史工单问题相关的问答对。
|
||||
返回格式为JSON数组,例如:
|
||||
[
|
||||
{{
|
||||
"question": "如何远程启动车辆?",
|
||||
"answer": "远程启动车辆需要满足以下条件:1. 车辆处于P档 2. 手刹拉起 3. 车门已锁 4. 电池电量充足",
|
||||
"answer": "远程启动车辆需要满足以下条件:1. 车辆处于P档 2. 手刹拉起 3. 车门已锁 4. 电池电量充足。如果仍然无法启动,请检查车辆是否处于可启动状态。",
|
||||
"category": "远程控制",
|
||||
"confidence_score": 0.9
|
||||
"confidence_score": 0.9,
|
||||
"workorder_related": true
|
||||
}}
|
||||
]
|
||||
"""
|
||||
@@ -700,6 +722,52 @@ class TSPAgentAssistant(TSPAssistant):
|
||||
logger.error(f"提取知识失败: {e}")
|
||||
return []
|
||||
|
||||
def _get_workorder_insights(self) -> str:
|
||||
"""获取工单数据洞察"""
|
||||
try:
|
||||
# 获取工单数据
|
||||
workorders = self.get_workorders()
|
||||
if not isinstance(workorders, list):
|
||||
return "暂无工单数据"
|
||||
|
||||
# 分析工单数据
|
||||
categories = {}
|
||||
common_issues = []
|
||||
resolutions = []
|
||||
|
||||
for workorder in workorders[:20]: # 取最近20个工单
|
||||
category = workorder.get("category", "其他")
|
||||
categories[category] = categories.get(category, 0) + 1
|
||||
|
||||
# 提取常见问题
|
||||
title = workorder.get("title", "")
|
||||
description = workorder.get("description", "")
|
||||
if title and len(title) > 5:
|
||||
common_issues.append(title)
|
||||
|
||||
# 提取解决方案(如果有)
|
||||
resolution = workorder.get("resolution", "")
|
||||
if resolution and len(resolution) > 10:
|
||||
resolutions.append(resolution[:100]) # 截取前100字符
|
||||
|
||||
# 构建工单洞察文本
|
||||
insights = f"""
|
||||
工单统计:
|
||||
- 总工单数:{len(workorders)}
|
||||
- 问题分类分布:{dict(list(categories.items())[:5])}
|
||||
|
||||
常见问题:
|
||||
{chr(10).join(common_issues[:10])}
|
||||
|
||||
解决方案示例:
|
||||
{chr(10).join(resolutions[:5])}
|
||||
"""
|
||||
return insights
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"获取工单洞察失败: {e}")
|
||||
return "获取工单数据失败"
|
||||
|
||||
def _parse_knowledge_manually(self, content: str) -> List[Dict[str, Any]]:
|
||||
"""手动解析知识内容"""
|
||||
try:
|
||||
|
||||
Binary file not shown.
BIN
src/web/__pycache__/websocket_server.cpython-311.pyc
Normal file
BIN
src/web/__pycache__/websocket_server.cpython-311.pyc
Normal file
Binary file not shown.
364
src/web/app.py
364
src/web/app.py
@@ -8,9 +8,13 @@ TSP助手预警管理Web应用
|
||||
import sys
|
||||
import os
|
||||
import json
|
||||
import pandas as pd
|
||||
from datetime import datetime, timedelta
|
||||
from flask import Flask, render_template, request, jsonify, redirect, url_for
|
||||
from openpyxl import Workbook
|
||||
from openpyxl.styles import Font
|
||||
from flask import Flask, render_template, request, jsonify, redirect, url_for, send_from_directory, send_file
|
||||
from flask_cors import CORS
|
||||
from werkzeug.utils import secure_filename
|
||||
|
||||
# 添加项目根目录到Python路径
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
@@ -24,6 +28,11 @@ from src.vehicle.vehicle_data_manager import VehicleDataManager
|
||||
app = Flask(__name__)
|
||||
CORS(app)
|
||||
|
||||
# 配置上传文件夹
|
||||
UPLOAD_FOLDER = 'uploads'
|
||||
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
|
||||
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 # 16MB max file size
|
||||
|
||||
# 初始化TSP助手和Agent助手
|
||||
assistant = TSPAssistant()
|
||||
agent_assistant = TSPAgentAssistant()
|
||||
@@ -541,6 +550,60 @@ def get_workorders():
|
||||
"priority": "medium",
|
||||
"status": "in_progress",
|
||||
"created_at": "2024-01-01T11:00:00Z"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"title": "蓝牙连接失败",
|
||||
"description": "用户无法通过蓝牙连接车辆",
|
||||
"category": "蓝牙功能",
|
||||
"priority": "high",
|
||||
"status": "open",
|
||||
"created_at": "2024-01-01T12:00:00Z"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"title": "车辆定位不准确",
|
||||
"description": "APP中显示的车辆位置与实际位置不符",
|
||||
"category": "定位功能",
|
||||
"priority": "medium",
|
||||
"status": "resolved",
|
||||
"created_at": "2024-01-01T13:00:00Z"
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"title": "远程解锁失败",
|
||||
"description": "用户无法通过APP远程解锁车辆",
|
||||
"category": "远程控制",
|
||||
"priority": "urgent",
|
||||
"status": "open",
|
||||
"created_at": "2024-01-01T14:00:00Z"
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"title": "APP闪退问题",
|
||||
"description": "用户反映APP在使用过程中频繁闪退",
|
||||
"category": "APP功能",
|
||||
"priority": "high",
|
||||
"status": "in_progress",
|
||||
"created_at": "2024-01-01T15:00:00Z"
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"title": "车辆状态更新延迟",
|
||||
"description": "车辆状态信息更新不及时,存在延迟",
|
||||
"category": "数据同步",
|
||||
"priority": "low",
|
||||
"status": "open",
|
||||
"created_at": "2024-01-01T16:00:00Z"
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"title": "用户认证失败",
|
||||
"description": "部分用户无法正常登录APP",
|
||||
"category": "用户认证",
|
||||
"priority": "high",
|
||||
"status": "resolved",
|
||||
"created_at": "2024-01-01T17:00:00Z"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -569,16 +632,313 @@ def create_workorder():
|
||||
except Exception as e:
|
||||
return jsonify({"error": str(e)}), 500
|
||||
|
||||
@app.route('/api/workorders/<int:workorder_id>')
|
||||
def get_workorder_details(workorder_id):
|
||||
"""获取工单详情"""
|
||||
try:
|
||||
# 这里应该从数据库获取工单详情
|
||||
# 暂时返回模拟数据
|
||||
workorder = {
|
||||
"id": workorder_id,
|
||||
"order_id": f"WO{workorder_id:06d}",
|
||||
"title": "车辆无法远程启动",
|
||||
"description": "用户反映APP中远程启动功能无法使用,点击启动按钮后没有任何反应,车辆也没有响应。",
|
||||
"category": "远程控制",
|
||||
"priority": "high",
|
||||
"status": "open",
|
||||
"created_at": "2024-01-01T10:00:00Z",
|
||||
"updated_at": "2024-01-01T10:00:00Z",
|
||||
"resolution": None,
|
||||
"satisfaction_score": None,
|
||||
"conversations": [
|
||||
{
|
||||
"id": 1,
|
||||
"user_message": "我的车辆无法远程启动",
|
||||
"assistant_response": "我了解您的问题。让我帮您排查一下远程启动功能的问题。",
|
||||
"timestamp": "2024-01-01T10:05:00Z"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"user_message": "点击启动按钮后没有任何反应",
|
||||
"assistant_response": "这种情况通常是由于网络连接或车辆状态问题导致的。请检查车辆是否处于可启动状态。",
|
||||
"timestamp": "2024-01-01T10:10:00Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
return jsonify(workorder)
|
||||
except Exception as e:
|
||||
return jsonify({"error": str(e)}), 500
|
||||
|
||||
@app.route('/api/workorders/<int:workorder_id>', methods=['PUT'])
|
||||
def update_workorder(workorder_id):
|
||||
"""更新工单"""
|
||||
try:
|
||||
data = request.get_json()
|
||||
|
||||
# 验证必填字段
|
||||
if not data.get('title') or not data.get('description'):
|
||||
return jsonify({"error": "标题和描述不能为空"}), 400
|
||||
|
||||
# 这里应该更新数据库中的工单
|
||||
# 暂时返回成功响应,实际应用中应该调用数据库更新
|
||||
updated_workorder = {
|
||||
"id": workorder_id,
|
||||
"title": data.get('title'),
|
||||
"description": data.get('description'),
|
||||
"category": data.get('category', '技术问题'),
|
||||
"priority": data.get('priority', 'medium'),
|
||||
"status": data.get('status', 'open'),
|
||||
"resolution": data.get('resolution'),
|
||||
"satisfaction_score": data.get('satisfaction_score'),
|
||||
"updated_at": datetime.now().isoformat()
|
||||
}
|
||||
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"message": "工单更新成功",
|
||||
"workorder": updated_workorder
|
||||
})
|
||||
except Exception as e:
|
||||
return jsonify({"error": str(e)}), 500
|
||||
|
||||
# 分析相关API
|
||||
@app.route('/api/analytics')
|
||||
def get_analytics():
|
||||
"""获取分析数据"""
|
||||
try:
|
||||
analytics = assistant.generate_analytics("last_7_days")
|
||||
time_range = request.args.get('timeRange', '30')
|
||||
dimension = request.args.get('dimension', 'workorders')
|
||||
|
||||
# 生成模拟分析数据
|
||||
analytics = generate_analytics_data(int(time_range), dimension)
|
||||
return jsonify(analytics)
|
||||
except Exception as e:
|
||||
return jsonify({"error": str(e)}), 500
|
||||
|
||||
def generate_analytics_data(days, dimension):
|
||||
"""生成分析数据"""
|
||||
import random
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
# 生成时间序列数据
|
||||
trend_data = []
|
||||
for i in range(days):
|
||||
date = (datetime.now() - timedelta(days=days-i-1)).strftime('%Y-%m-%d')
|
||||
workorders = random.randint(5, 25)
|
||||
alerts = random.randint(0, 10)
|
||||
trend_data.append({
|
||||
'date': date,
|
||||
'workorders': workorders,
|
||||
'alerts': alerts
|
||||
})
|
||||
|
||||
# 工单统计
|
||||
workorders_stats = {
|
||||
'total': random.randint(100, 500),
|
||||
'open': random.randint(10, 50),
|
||||
'in_progress': random.randint(5, 30),
|
||||
'resolved': random.randint(50, 200),
|
||||
'closed': random.randint(20, 100),
|
||||
'by_category': {
|
||||
'技术问题': random.randint(20, 80),
|
||||
'业务问题': random.randint(15, 60),
|
||||
'系统故障': random.randint(10, 40),
|
||||
'功能需求': random.randint(5, 30),
|
||||
'其他': random.randint(5, 20)
|
||||
},
|
||||
'by_priority': {
|
||||
'low': random.randint(20, 60),
|
||||
'medium': random.randint(30, 80),
|
||||
'high': random.randint(10, 40),
|
||||
'urgent': random.randint(5, 20)
|
||||
}
|
||||
}
|
||||
|
||||
# 满意度分析
|
||||
satisfaction_stats = {
|
||||
'average': round(random.uniform(3.5, 4.8), 1),
|
||||
'distribution': {
|
||||
'1': random.randint(0, 5),
|
||||
'2': random.randint(0, 10),
|
||||
'3': random.randint(5, 20),
|
||||
'4': random.randint(20, 50),
|
||||
'5': random.randint(30, 80)
|
||||
}
|
||||
}
|
||||
|
||||
# 预警统计
|
||||
alerts_stats = {
|
||||
'total': random.randint(50, 200),
|
||||
'active': random.randint(5, 30),
|
||||
'resolved': random.randint(20, 100),
|
||||
'by_level': {
|
||||
'low': random.randint(10, 40),
|
||||
'medium': random.randint(15, 50),
|
||||
'high': random.randint(5, 25),
|
||||
'critical': random.randint(2, 10)
|
||||
}
|
||||
}
|
||||
|
||||
# 性能指标
|
||||
performance_stats = {
|
||||
'response_time': round(random.uniform(0.5, 2.0), 2),
|
||||
'uptime': round(random.uniform(95, 99.9), 1),
|
||||
'error_rate': round(random.uniform(0.1, 2.0), 2),
|
||||
'throughput': random.randint(1000, 5000)
|
||||
}
|
||||
|
||||
return {
|
||||
'trend': trend_data,
|
||||
'workorders': workorders_stats,
|
||||
'satisfaction': satisfaction_stats,
|
||||
'alerts': alerts_stats,
|
||||
'performance': performance_stats,
|
||||
'summary': {
|
||||
'total_workorders': workorders_stats['total'],
|
||||
'resolution_rate': round((workorders_stats['resolved'] / workorders_stats['total']) * 100, 1) if workorders_stats['total'] > 0 else 0,
|
||||
'avg_satisfaction': satisfaction_stats['average'],
|
||||
'active_alerts': alerts_stats['active']
|
||||
}
|
||||
}
|
||||
|
||||
@app.route('/api/analytics/export')
|
||||
def export_analytics():
|
||||
"""导出分析报告"""
|
||||
try:
|
||||
# 生成Excel报告
|
||||
analytics = generate_analytics_data(30, 'workorders')
|
||||
|
||||
# 创建工作簿
|
||||
wb = Workbook()
|
||||
ws = wb.active
|
||||
ws.title = "分析报告"
|
||||
|
||||
# 添加标题
|
||||
ws['A1'] = 'TSP智能助手分析报告'
|
||||
ws['A1'].font = Font(size=16, bold=True)
|
||||
|
||||
# 添加工单统计
|
||||
ws['A3'] = '工单统计'
|
||||
ws['A3'].font = Font(bold=True)
|
||||
ws['A4'] = '总工单数'
|
||||
ws['B4'] = analytics['workorders']['total']
|
||||
ws['A5'] = '待处理'
|
||||
ws['B5'] = analytics['workorders']['open']
|
||||
ws['A6'] = '已解决'
|
||||
ws['B6'] = analytics['workorders']['resolved']
|
||||
|
||||
# 保存文件
|
||||
report_path = 'uploads/analytics_report.xlsx'
|
||||
os.makedirs('uploads', exist_ok=True)
|
||||
wb.save(report_path)
|
||||
|
||||
return send_file(report_path, as_attachment=True, download_name='analytics_report.xlsx')
|
||||
|
||||
except Exception as e:
|
||||
return jsonify({"error": str(e)}), 500
|
||||
|
||||
# 工单导入相关API
|
||||
@app.route('/api/workorders/import', methods=['POST'])
|
||||
def import_workorders():
|
||||
"""导入Excel工单文件"""
|
||||
try:
|
||||
# 检查是否有文件上传
|
||||
if 'file' not in request.files:
|
||||
return jsonify({"error": "没有上传文件"}), 400
|
||||
|
||||
file = request.files['file']
|
||||
if file.filename == '':
|
||||
return jsonify({"error": "没有选择文件"}), 400
|
||||
|
||||
if not file.filename.endswith(('.xlsx', '.xls')):
|
||||
return jsonify({"error": "只支持Excel文件(.xlsx, .xls)"}), 400
|
||||
|
||||
# 保存上传的文件
|
||||
filename = secure_filename(file.filename)
|
||||
upload_path = os.path.join('uploads', filename)
|
||||
os.makedirs('uploads', exist_ok=True)
|
||||
file.save(upload_path)
|
||||
|
||||
# 解析Excel文件
|
||||
try:
|
||||
df = pd.read_excel(upload_path)
|
||||
imported_workorders = []
|
||||
|
||||
# 处理每一行数据
|
||||
for index, row in df.iterrows():
|
||||
# 根据Excel列名映射到工单字段
|
||||
workorder = {
|
||||
"id": len(assistant.work_orders) + index + 1, # 生成新ID
|
||||
"order_id": f"WO{len(assistant.work_orders) + index + 1:06d}",
|
||||
"title": str(row.get('标题', row.get('title', f'导入工单 {index + 1}'))),
|
||||
"description": str(row.get('描述', row.get('description', ''))),
|
||||
"category": str(row.get('分类', row.get('category', '技术问题'))),
|
||||
"priority": str(row.get('优先级', row.get('priority', 'medium'))),
|
||||
"status": str(row.get('状态', row.get('status', 'open'))),
|
||||
"created_at": datetime.now().isoformat(),
|
||||
"updated_at": datetime.now().isoformat(),
|
||||
"resolution": str(row.get('解决方案', row.get('resolution', ''))) if pd.notna(row.get('解决方案', row.get('resolution'))) else None,
|
||||
"satisfaction_score": int(row.get('满意度', row.get('satisfaction_score', 0))) if pd.notna(row.get('满意度', row.get('satisfaction_score'))) else None
|
||||
}
|
||||
|
||||
# 添加到工单列表(这里应该保存到数据库)
|
||||
assistant.work_orders.append(workorder)
|
||||
imported_workorders.append(workorder)
|
||||
|
||||
# 清理上传的文件
|
||||
os.remove(upload_path)
|
||||
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"message": f"成功导入 {len(imported_workorders)} 个工单",
|
||||
"imported_count": len(imported_workorders),
|
||||
"workorders": imported_workorders
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
# 清理上传的文件
|
||||
if os.path.exists(upload_path):
|
||||
os.remove(upload_path)
|
||||
return jsonify({"error": f"解析Excel文件失败: {str(e)}"}), 400
|
||||
|
||||
except Exception as e:
|
||||
return jsonify({"error": str(e)}), 500
|
||||
|
||||
@app.route('/api/workorders/import/template')
|
||||
def download_import_template():
|
||||
"""下载工单导入模板"""
|
||||
try:
|
||||
# 创建模板数据
|
||||
template_data = {
|
||||
'标题': ['车辆无法启动', '空调不制冷', '导航系统故障'],
|
||||
'描述': ['用户反映车辆无法正常启动', '空调系统无法制冷', '导航系统显示异常'],
|
||||
'分类': ['技术问题', '技术问题', '技术问题'],
|
||||
'优先级': ['high', 'medium', 'low'],
|
||||
'状态': ['open', 'in_progress', 'resolved'],
|
||||
'解决方案': ['检查电池和启动系统', '检查制冷剂和压缩机', '更新导航软件'],
|
||||
'满意度': [5, 4, 5]
|
||||
}
|
||||
|
||||
df = pd.DataFrame(template_data)
|
||||
|
||||
# 保存为Excel文件
|
||||
template_path = 'uploads/workorder_template.xlsx'
|
||||
os.makedirs('uploads', exist_ok=True)
|
||||
df.to_excel(template_path, index=False)
|
||||
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"template_url": f"/uploads/workorder_template.xlsx"
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
return jsonify({"error": str(e)}), 500
|
||||
|
||||
@app.route('/uploads/<filename>')
|
||||
def uploaded_file(filename):
|
||||
"""提供上传文件的下载服务"""
|
||||
return send_from_directory(app.config['UPLOAD_FOLDER'], filename)
|
||||
|
||||
# 系统设置相关API
|
||||
@app.route('/api/settings')
|
||||
def get_settings():
|
||||
|
||||
@@ -429,3 +429,178 @@ body {
|
||||
background-color: #d1ecf1;
|
||||
border-color: #17a2b8;
|
||||
}
|
||||
|
||||
/* 预设规则卡片样式 */
|
||||
.preset-card {
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
border: 2px solid transparent;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.preset-card:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 8px 25px rgba(0,0,0,0.15);
|
||||
border-color: #007bff;
|
||||
}
|
||||
|
||||
.preset-card.selected {
|
||||
border-color: #28a745;
|
||||
background-color: #f8fff9;
|
||||
}
|
||||
|
||||
.preset-card .card-body {
|
||||
padding: 1.5rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.preset-card h6 {
|
||||
margin-bottom: 0.5rem;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.preset-card p {
|
||||
margin-bottom: 1rem;
|
||||
color: #6c757d;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.preset-params {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 0.5rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.preset-params .badge {
|
||||
font-size: 0.7rem;
|
||||
padding: 0.25rem 0.5rem;
|
||||
}
|
||||
|
||||
/* 预设模板模态框样式 */
|
||||
#presetModal .modal-dialog {
|
||||
max-width: 1200px;
|
||||
}
|
||||
|
||||
#presetModal .modal-body {
|
||||
max-height: 70vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
/* 预设规则分类标题 */
|
||||
#presetModal h6 {
|
||||
font-weight: 600;
|
||||
margin-bottom: 1rem;
|
||||
padding-bottom: 0.5rem;
|
||||
border-bottom: 2px solid;
|
||||
}
|
||||
|
||||
#presetModal h6.text-primary {
|
||||
border-bottom-color: #007bff;
|
||||
}
|
||||
|
||||
#presetModal h6.text-success {
|
||||
border-bottom-color: #28a745;
|
||||
}
|
||||
|
||||
#presetModal h6.text-info {
|
||||
border-bottom-color: #17a2b8;
|
||||
}
|
||||
|
||||
#presetModal h6.text-warning {
|
||||
border-bottom-color: #ffc107;
|
||||
}
|
||||
|
||||
/* 预设卡片图标样式 */
|
||||
.preset-card i {
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.preset-card:hover i {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
/* 预设卡片选中状态 */
|
||||
.preset-card.selected i {
|
||||
color: #28a745 !important;
|
||||
}
|
||||
|
||||
.preset-card.selected h6 {
|
||||
color: #28a745;
|
||||
}
|
||||
|
||||
/* 响应式预设卡片 */
|
||||
@media (max-width: 768px) {
|
||||
.preset-card .card-body {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.preset-card h6 {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.preset-card p {
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.preset-params .badge {
|
||||
font-size: 0.65rem;
|
||||
padding: 0.2rem 0.4rem;
|
||||
}
|
||||
}
|
||||
|
||||
/* 预设规则快速选择 */
|
||||
.preset-quick-select {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
margin-bottom: 1rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.preset-quick-select .btn {
|
||||
font-size: 0.8rem;
|
||||
padding: 0.25rem 0.75rem;
|
||||
}
|
||||
|
||||
/* 预设规则预览 */
|
||||
.preset-preview {
|
||||
background-color: #f8f9fa;
|
||||
border: 1px solid #e9ecef;
|
||||
border-radius: 0.375rem;
|
||||
padding: 1rem;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.preset-preview h6 {
|
||||
color: #495057;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.preset-preview .preview-params {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.preset-preview .preview-param {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 0.25rem 0;
|
||||
border-bottom: 1px solid #e9ecef;
|
||||
}
|
||||
|
||||
.preset-preview .preview-param:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.preset-preview .preview-param strong {
|
||||
color: #495057;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.preset-preview .preview-param span {
|
||||
color: #6c757d;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
@@ -1198,9 +1198,14 @@ class TSPDashboard {
|
||||
</div>
|
||||
</div>
|
||||
<div class="ms-3">
|
||||
<button class="btn btn-sm btn-outline-primary" onclick="dashboard.updateWorkOrder(${workorder.id})">
|
||||
<i class="fas fa-edit"></i>
|
||||
</button>
|
||||
<div class="btn-group" role="group">
|
||||
<button class="btn btn-sm btn-outline-info" onclick="dashboard.viewWorkOrderDetails(${workorder.id})" title="查看详情">
|
||||
<i class="fas fa-eye"></i>
|
||||
</button>
|
||||
<button class="btn btn-sm btn-outline-primary" onclick="dashboard.updateWorkOrder(${workorder.id})" title="编辑">
|
||||
<i class="fas fa-edit"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1262,17 +1267,748 @@ class TSPDashboard {
|
||||
}
|
||||
}
|
||||
|
||||
async viewWorkOrderDetails(workorderId) {
|
||||
try {
|
||||
const response = await fetch(`/api/workorders/${workorderId}`);
|
||||
const workorder = await response.json();
|
||||
|
||||
if (workorder.error) {
|
||||
this.showNotification('获取工单详情失败', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
this.showWorkOrderDetailsModal(workorder);
|
||||
} catch (error) {
|
||||
console.error('获取工单详情失败:', error);
|
||||
this.showNotification('获取工单详情失败', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
showWorkOrderDetailsModal(workorder) {
|
||||
// 创建模态框HTML
|
||||
const modalHtml = `
|
||||
<div class="modal fade" id="workOrderDetailsModal" tabindex="-1">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">工单详情 - ${workorder.order_id || workorder.id}</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-6">
|
||||
<h6>基本信息</h6>
|
||||
<table class="table table-sm">
|
||||
<tr>
|
||||
<td><strong>工单号:</strong></td>
|
||||
<td>${workorder.order_id || workorder.id}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>标题:</strong></td>
|
||||
<td>${workorder.title}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>分类:</strong></td>
|
||||
<td>${workorder.category}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>优先级:</strong></td>
|
||||
<td><span class="badge bg-${this.getPriorityColor(workorder.priority)}">${this.getPriorityText(workorder.priority)}</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>状态:</strong></td>
|
||||
<td><span class="badge bg-${this.getStatusColor(workorder.status)}">${this.getStatusText(workorder.status)}</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>创建时间:</strong></td>
|
||||
<td>${new Date(workorder.created_at).toLocaleString()}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>更新时间:</strong></td>
|
||||
<td>${new Date(workorder.updated_at).toLocaleString()}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<h6>问题描述</h6>
|
||||
<div class="border p-3 rounded">
|
||||
${workorder.description}
|
||||
</div>
|
||||
${workorder.resolution ? `
|
||||
<h6 class="mt-3">解决方案</h6>
|
||||
<div class="border p-3 rounded bg-light">
|
||||
${workorder.resolution}
|
||||
</div>
|
||||
` : ''}
|
||||
${workorder.satisfaction_score ? `
|
||||
<h6 class="mt-3">满意度评分</h6>
|
||||
<div class="border p-3 rounded">
|
||||
<div class="progress">
|
||||
<div class="progress-bar" style="width: ${workorder.satisfaction_score * 100}%"></div>
|
||||
</div>
|
||||
<small class="text-muted">${workorder.satisfaction_score}/5.0</small>
|
||||
</div>
|
||||
` : ''}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
${workorder.conversations && workorder.conversations.length > 0 ? `
|
||||
<h6>对话记录</h6>
|
||||
<div class="conversation-history" style="max-height: 300px; overflow-y: auto;">
|
||||
${workorder.conversations.map(conv => `
|
||||
<div class="border-bottom pb-2 mb-2">
|
||||
<div class="d-flex justify-content-between">
|
||||
<small class="text-muted">${new Date(conv.timestamp).toLocaleString()}</small>
|
||||
</div>
|
||||
<div class="mb-1">
|
||||
<strong>用户:</strong> ${conv.user_message}
|
||||
</div>
|
||||
<div>
|
||||
<strong>助手:</strong> ${conv.assistant_response}
|
||||
</div>
|
||||
</div>
|
||||
`).join('')}
|
||||
</div>
|
||||
` : ''}
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button>
|
||||
<button type="button" class="btn btn-primary" onclick="dashboard.updateWorkOrder(${workorder.id})">编辑工单</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// 移除已存在的模态框
|
||||
const existingModal = document.getElementById('workOrderDetailsModal');
|
||||
if (existingModal) {
|
||||
existingModal.remove();
|
||||
}
|
||||
|
||||
// 添加新的模态框到页面
|
||||
document.body.insertAdjacentHTML('beforeend', modalHtml);
|
||||
|
||||
// 显示模态框
|
||||
const modal = new bootstrap.Modal(document.getElementById('workOrderDetailsModal'));
|
||||
modal.show();
|
||||
|
||||
// 模态框关闭时移除DOM元素
|
||||
document.getElementById('workOrderDetailsModal').addEventListener('hidden.bs.modal', function() {
|
||||
this.remove();
|
||||
});
|
||||
}
|
||||
|
||||
async updateWorkOrder(workorderId) {
|
||||
try {
|
||||
// 获取工单详情
|
||||
const response = await fetch(`/api/workorders/${workorderId}`);
|
||||
const workorder = await response.json();
|
||||
|
||||
if (response.ok) {
|
||||
this.showEditWorkOrderModal(workorder);
|
||||
} else {
|
||||
throw new Error(workorder.error || '获取工单详情失败');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取工单详情失败:', error);
|
||||
this.showNotification('获取工单详情失败: ' + error.message, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
showEditWorkOrderModal(workorder) {
|
||||
// 创建编辑工单模态框
|
||||
const modalHtml = `
|
||||
<div class="modal fade" id="editWorkOrderModal" tabindex="-1" aria-labelledby="editWorkOrderModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="editWorkOrderModalLabel">编辑工单 #${workorder.id}</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form id="editWorkOrderForm">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<div class="mb-3">
|
||||
<label for="editTitle" class="form-label">标题 *</label>
|
||||
<input type="text" class="form-control" id="editTitle" value="${workorder.title}" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="mb-3">
|
||||
<label for="editPriority" class="form-label">优先级</label>
|
||||
<select class="form-select" id="editPriority">
|
||||
<option value="low" ${workorder.priority === 'low' ? 'selected' : ''}>低</option>
|
||||
<option value="medium" ${workorder.priority === 'medium' ? 'selected' : ''}>中</option>
|
||||
<option value="high" ${workorder.priority === 'high' ? 'selected' : ''}>高</option>
|
||||
<option value="urgent" ${workorder.priority === 'urgent' ? 'selected' : ''}>紧急</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
<label for="editCategory" class="form-label">分类</label>
|
||||
<select class="form-select" id="editCategory">
|
||||
<option value="技术问题" ${workorder.category === '技术问题' ? 'selected' : ''}>技术问题</option>
|
||||
<option value="业务问题" ${workorder.category === '业务问题' ? 'selected' : ''}>业务问题</option>
|
||||
<option value="系统故障" ${workorder.category === '系统故障' ? 'selected' : ''}>系统故障</option>
|
||||
<option value="功能需求" ${workorder.category === '功能需求' ? 'selected' : ''}>功能需求</option>
|
||||
<option value="其他" ${workorder.category === '其他' ? 'selected' : ''}>其他</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
<label for="editStatus" class="form-label">状态</label>
|
||||
<select class="form-select" id="editStatus">
|
||||
<option value="open" ${workorder.status === 'open' ? 'selected' : ''}>待处理</option>
|
||||
<option value="in_progress" ${workorder.status === 'in_progress' ? 'selected' : ''}>处理中</option>
|
||||
<option value="resolved" ${workorder.status === 'resolved' ? 'selected' : ''}>已解决</option>
|
||||
<option value="closed" ${workorder.status === 'closed' ? 'selected' : ''}>已关闭</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="editDescription" class="form-label">描述 *</label>
|
||||
<textarea class="form-control" id="editDescription" rows="4" required>${workorder.description}</textarea>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="editResolution" class="form-label">解决方案</label>
|
||||
<textarea class="form-control" id="editResolution" rows="3" placeholder="请输入解决方案...">${workorder.resolution || ''}</textarea>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
<label for="editSatisfactionScore" class="form-label">满意度评分 (1-5)</label>
|
||||
<input type="number" class="form-control" id="editSatisfactionScore" min="1" max="5" value="${workorder.satisfaction_score || ''}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
|
||||
<button type="button" class="btn btn-primary" onclick="dashboard.saveWorkOrder(${workorder.id})">保存修改</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// 移除已存在的模态框
|
||||
const existingModal = document.getElementById('editWorkOrderModal');
|
||||
if (existingModal) {
|
||||
existingModal.remove();
|
||||
}
|
||||
|
||||
// 添加新模态框到页面
|
||||
document.body.insertAdjacentHTML('beforeend', modalHtml);
|
||||
|
||||
// 显示模态框
|
||||
const modal = new bootstrap.Modal(document.getElementById('editWorkOrderModal'));
|
||||
modal.show();
|
||||
|
||||
// 模态框关闭时清理
|
||||
document.getElementById('editWorkOrderModal').addEventListener('hidden.bs.modal', function() {
|
||||
this.remove();
|
||||
});
|
||||
}
|
||||
|
||||
async saveWorkOrder(workorderId) {
|
||||
try {
|
||||
// 获取表单数据
|
||||
const formData = {
|
||||
title: document.getElementById('editTitle').value,
|
||||
description: document.getElementById('editDescription').value,
|
||||
category: document.getElementById('editCategory').value,
|
||||
priority: document.getElementById('editPriority').value,
|
||||
status: document.getElementById('editStatus').value,
|
||||
resolution: document.getElementById('editResolution').value,
|
||||
satisfaction_score: parseInt(document.getElementById('editSatisfactionScore').value) || null
|
||||
};
|
||||
|
||||
// 验证必填字段
|
||||
if (!formData.title.trim() || !formData.description.trim()) {
|
||||
this.showNotification('标题和描述不能为空', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
// 发送更新请求
|
||||
const response = await fetch(`/api/workorders/${workorderId}`, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(formData)
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok) {
|
||||
this.showNotification('工单更新成功', 'success');
|
||||
// 关闭模态框
|
||||
const modal = bootstrap.Modal.getInstance(document.getElementById('editWorkOrderModal'));
|
||||
modal.hide();
|
||||
// 刷新工单列表
|
||||
this.loadWorkOrders();
|
||||
} else {
|
||||
throw new Error(result.error || '更新工单失败');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('更新工单失败:', error);
|
||||
this.showNotification('更新工单失败: ' + error.message, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
// 工单导入功能
|
||||
showImportModal() {
|
||||
// 显示导入模态框
|
||||
const modal = new bootstrap.Modal(document.getElementById('importWorkOrderModal'));
|
||||
modal.show();
|
||||
|
||||
// 重置表单
|
||||
document.getElementById('excel-file-input').value = '';
|
||||
document.getElementById('import-progress').classList.add('d-none');
|
||||
document.getElementById('import-result').classList.add('d-none');
|
||||
}
|
||||
|
||||
async downloadTemplate() {
|
||||
try {
|
||||
const response = await fetch('/api/workorders/import/template');
|
||||
const result = await response.json();
|
||||
|
||||
if (result.success) {
|
||||
// 创建下载链接
|
||||
const link = document.createElement('a');
|
||||
link.href = result.template_url;
|
||||
link.download = '工单导入模板.xlsx';
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
|
||||
this.showNotification('模板下载成功', 'success');
|
||||
} else {
|
||||
throw new Error(result.error || '下载模板失败');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('下载模板失败:', error);
|
||||
this.showNotification('下载模板失败: ' + error.message, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
async importWorkOrders() {
|
||||
const fileInput = document.getElementById('excel-file-input');
|
||||
const file = fileInput.files[0];
|
||||
|
||||
if (!file) {
|
||||
this.showNotification('请选择要导入的Excel文件', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
// 验证文件类型
|
||||
if (!file.name.match(/\.(xlsx|xls)$/)) {
|
||||
this.showNotification('只支持Excel文件(.xlsx, .xls)', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
// 验证文件大小
|
||||
if (file.size > 16 * 1024 * 1024) {
|
||||
this.showNotification('文件大小不能超过16MB', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
// 显示进度条
|
||||
document.getElementById('import-progress').classList.remove('d-none');
|
||||
document.getElementById('import-result').classList.add('d-none');
|
||||
|
||||
try {
|
||||
// 创建FormData
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
|
||||
// 发送导入请求
|
||||
const response = await fetch('/api/workorders/import', {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok && result.success) {
|
||||
// 显示成功消息
|
||||
document.getElementById('import-progress').classList.add('d-none');
|
||||
document.getElementById('import-result').classList.remove('d-none');
|
||||
document.getElementById('import-success-message').textContent =
|
||||
`成功导入 ${result.imported_count} 个工单`;
|
||||
|
||||
this.showNotification(result.message, 'success');
|
||||
|
||||
// 刷新工单列表
|
||||
this.loadWorkOrders();
|
||||
|
||||
// 3秒后关闭模态框
|
||||
setTimeout(() => {
|
||||
const modal = bootstrap.Modal.getInstance(document.getElementById('importWorkOrderModal'));
|
||||
modal.hide();
|
||||
}, 3000);
|
||||
|
||||
} else {
|
||||
throw new Error(result.error || '导入工单失败');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('导入工单失败:', error);
|
||||
document.getElementById('import-progress').classList.add('d-none');
|
||||
this.showNotification('导入工单失败: ' + error.message, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
// 数据分析
|
||||
async loadAnalytics() {
|
||||
try {
|
||||
const response = await fetch('/api/analytics');
|
||||
const analytics = await response.json();
|
||||
this.updateAnalyticsDisplay(analytics);
|
||||
this.initializeCharts();
|
||||
} catch (error) {
|
||||
console.error('加载分析数据失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化图表
|
||||
initializeCharts() {
|
||||
this.charts = {};
|
||||
this.updateCharts();
|
||||
}
|
||||
|
||||
// 更新所有图表
|
||||
async updateCharts() {
|
||||
try {
|
||||
const timeRange = document.getElementById('timeRange').value;
|
||||
const chartType = document.getElementById('chartType').value;
|
||||
const dataDimension = document.getElementById('dataDimension').value;
|
||||
|
||||
// 获取数据
|
||||
const response = await fetch(`/api/analytics?timeRange=${timeRange}&dimension=${dataDimension}`);
|
||||
const data = await response.json();
|
||||
|
||||
// 更新统计卡片
|
||||
this.updateStatisticsCards(data);
|
||||
|
||||
// 更新图表
|
||||
this.updateMainChart(data, chartType);
|
||||
this.updateDistributionChart(data);
|
||||
this.updateTrendChart(data);
|
||||
this.updatePriorityChart(data);
|
||||
|
||||
// 更新分析报告
|
||||
this.updateAnalyticsReport(data);
|
||||
|
||||
} catch (error) {
|
||||
console.error('更新图表失败:', error);
|
||||
this.showNotification('更新图表失败: ' + error.message, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
// 更新统计卡片
|
||||
updateStatisticsCards(data) {
|
||||
const total = data.workorders?.total || 0;
|
||||
const open = data.workorders?.open || 0;
|
||||
const resolved = data.workorders?.resolved || 0;
|
||||
const avgSatisfaction = data.satisfaction?.average || 0;
|
||||
|
||||
document.getElementById('totalWorkorders').textContent = total;
|
||||
document.getElementById('openWorkorders').textContent = open;
|
||||
document.getElementById('resolvedWorkorders').textContent = resolved;
|
||||
document.getElementById('avgSatisfaction').textContent = avgSatisfaction.toFixed(1);
|
||||
|
||||
// 更新进度条
|
||||
if (total > 0) {
|
||||
document.getElementById('openProgress').style.width = `${(open / total) * 100}%`;
|
||||
document.getElementById('resolvedProgress').style.width = `${(resolved / total) * 100}%`;
|
||||
document.getElementById('satisfactionProgress').style.width = `${(avgSatisfaction / 5) * 100}%`;
|
||||
}
|
||||
}
|
||||
|
||||
// 更新主图表
|
||||
updateMainChart(data, chartType) {
|
||||
const ctx = document.getElementById('mainChart').getContext('2d');
|
||||
|
||||
// 销毁现有图表
|
||||
if (this.charts.mainChart) {
|
||||
this.charts.mainChart.destroy();
|
||||
}
|
||||
|
||||
const chartData = this.prepareChartData(data, chartType);
|
||||
|
||||
this.charts.mainChart = new Chart(ctx, {
|
||||
type: chartType,
|
||||
data: chartData,
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
plugins: {
|
||||
title: {
|
||||
display: true,
|
||||
text: '数据分析趋势'
|
||||
},
|
||||
legend: {
|
||||
display: true,
|
||||
position: 'top'
|
||||
}
|
||||
},
|
||||
scales: chartType === 'pie' || chartType === 'doughnut' ? {} : {
|
||||
x: {
|
||||
display: true,
|
||||
title: {
|
||||
display: true,
|
||||
text: '时间'
|
||||
}
|
||||
},
|
||||
y: {
|
||||
display: true,
|
||||
title: {
|
||||
display: true,
|
||||
text: '数量'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 更新分布图表
|
||||
updateDistributionChart(data) {
|
||||
const ctx = document.getElementById('distributionChart').getContext('2d');
|
||||
|
||||
if (this.charts.distributionChart) {
|
||||
this.charts.distributionChart.destroy();
|
||||
}
|
||||
|
||||
const categories = data.workorders?.by_category || {};
|
||||
const labels = Object.keys(categories);
|
||||
const values = Object.values(categories);
|
||||
|
||||
this.charts.distributionChart = new Chart(ctx, {
|
||||
type: 'doughnut',
|
||||
data: {
|
||||
labels: labels,
|
||||
datasets: [{
|
||||
data: values,
|
||||
backgroundColor: [
|
||||
'#FF6384',
|
||||
'#36A2EB',
|
||||
'#FFCE56',
|
||||
'#4BC0C0',
|
||||
'#9966FF',
|
||||
'#FF9F40'
|
||||
]
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
plugins: {
|
||||
title: {
|
||||
display: true,
|
||||
text: '工单分类分布'
|
||||
},
|
||||
legend: {
|
||||
display: true,
|
||||
position: 'bottom'
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 更新趋势图表
|
||||
updateTrendChart(data) {
|
||||
const ctx = document.getElementById('trendChart').getContext('2d');
|
||||
|
||||
if (this.charts.trendChart) {
|
||||
this.charts.trendChart.destroy();
|
||||
}
|
||||
|
||||
const trendData = data.trend || [];
|
||||
const labels = trendData.map(item => item.date);
|
||||
const workorders = trendData.map(item => item.workorders);
|
||||
const alerts = trendData.map(item => item.alerts);
|
||||
|
||||
this.charts.trendChart = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: labels,
|
||||
datasets: [{
|
||||
label: '工单数量',
|
||||
data: workorders,
|
||||
borderColor: '#36A2EB',
|
||||
backgroundColor: 'rgba(54, 162, 235, 0.1)',
|
||||
tension: 0.4
|
||||
}, {
|
||||
label: '预警数量',
|
||||
data: alerts,
|
||||
borderColor: '#FF6384',
|
||||
backgroundColor: 'rgba(255, 99, 132, 0.1)',
|
||||
tension: 0.4
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
plugins: {
|
||||
title: {
|
||||
display: true,
|
||||
text: '时间趋势分析'
|
||||
}
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
display: true,
|
||||
title: {
|
||||
display: true,
|
||||
text: '日期'
|
||||
}
|
||||
},
|
||||
y: {
|
||||
display: true,
|
||||
title: {
|
||||
display: true,
|
||||
text: '数量'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 更新优先级图表
|
||||
updatePriorityChart(data) {
|
||||
const ctx = document.getElementById('priorityChart').getContext('2d');
|
||||
|
||||
if (this.charts.priorityChart) {
|
||||
this.charts.priorityChart.destroy();
|
||||
}
|
||||
|
||||
const priorities = data.workorders?.by_priority || {};
|
||||
const labels = Object.keys(priorities).map(p => this.getPriorityText(p));
|
||||
const values = Object.values(priorities);
|
||||
|
||||
this.charts.priorityChart = new Chart(ctx, {
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: labels,
|
||||
datasets: [{
|
||||
label: '工单数量',
|
||||
data: values,
|
||||
backgroundColor: [
|
||||
'#28a745', // 低 - 绿色
|
||||
'#ffc107', // 中 - 黄色
|
||||
'#fd7e14', // 高 - 橙色
|
||||
'#dc3545' // 紧急 - 红色
|
||||
]
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
plugins: {
|
||||
title: {
|
||||
display: true,
|
||||
text: '优先级分布'
|
||||
}
|
||||
},
|
||||
scales: {
|
||||
y: {
|
||||
beginAtZero: true
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 准备图表数据
|
||||
prepareChartData(data, chartType) {
|
||||
const trendData = data.trend || [];
|
||||
const labels = trendData.map(item => item.date);
|
||||
const workorders = trendData.map(item => item.workorders);
|
||||
|
||||
if (chartType === 'pie' || chartType === 'doughnut') {
|
||||
const categories = data.workorders?.by_category || {};
|
||||
return {
|
||||
labels: Object.keys(categories),
|
||||
datasets: [{
|
||||
data: Object.values(categories),
|
||||
backgroundColor: [
|
||||
'#FF6384',
|
||||
'#36A2EB',
|
||||
'#FFCE56',
|
||||
'#4BC0C0',
|
||||
'#9966FF',
|
||||
'#FF9F40'
|
||||
]
|
||||
}]
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
labels: labels,
|
||||
datasets: [{
|
||||
label: '工单数量',
|
||||
data: workorders,
|
||||
borderColor: '#36A2EB',
|
||||
backgroundColor: 'rgba(54, 162, 235, 0.1)',
|
||||
tension: chartType === 'line' ? 0.4 : 0
|
||||
}]
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// 导出图表
|
||||
exportChart(chartId) {
|
||||
if (this.charts[chartId]) {
|
||||
const link = document.createElement('a');
|
||||
link.download = `${chartId}_chart.png`;
|
||||
link.href = this.charts[chartId].toBase64Image();
|
||||
link.click();
|
||||
}
|
||||
}
|
||||
|
||||
// 全屏图表
|
||||
fullscreenChart(chartId) {
|
||||
// 这里可以实现全屏显示功能
|
||||
this.showNotification('全屏功能开发中', 'info');
|
||||
}
|
||||
|
||||
// 导出报告
|
||||
async exportReport() {
|
||||
try {
|
||||
const response = await fetch('/api/analytics/export');
|
||||
const blob = await response.blob();
|
||||
const url = window.URL.createObjectURL(blob);
|
||||
const link = document.createElement('a');
|
||||
link.href = url;
|
||||
link.download = 'analytics_report.xlsx';
|
||||
link.click();
|
||||
window.URL.revokeObjectURL(url);
|
||||
} catch (error) {
|
||||
console.error('导出报告失败:', error);
|
||||
this.showNotification('导出报告失败: ' + error.message, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
// 打印报告
|
||||
printReport() {
|
||||
window.print();
|
||||
}
|
||||
|
||||
updateAnalyticsDisplay(analytics) {
|
||||
// 更新分析报告
|
||||
const reportContainer = document.getElementById('analytics-report');
|
||||
|
||||
@@ -844,9 +844,17 @@
|
||||
<div class="card">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<h5><i class="fas fa-tasks me-2"></i>工单管理</h5>
|
||||
<button class="btn btn-primary btn-sm" data-bs-toggle="modal" data-bs-target="#createWorkOrderModal">
|
||||
<i class="fas fa-plus me-1"></i>创建工单
|
||||
</button>
|
||||
<div class="btn-group" role="group">
|
||||
<button class="btn btn-success btn-sm" onclick="dashboard.downloadTemplate()">
|
||||
<i class="fas fa-download me-1"></i>下载模板
|
||||
</button>
|
||||
<button class="btn btn-info btn-sm" onclick="dashboard.showImportModal()">
|
||||
<i class="fas fa-upload me-1"></i>导入工单
|
||||
</button>
|
||||
<button class="btn btn-primary btn-sm" data-bs-toggle="modal" data-bs-target="#createWorkOrderModal">
|
||||
<i class="fas fa-plus me-1"></i>创建工单
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="mb-3">
|
||||
@@ -914,43 +922,210 @@
|
||||
|
||||
<!-- 数据分析标签页 -->
|
||||
<div id="analytics-tab" class="tab-content" style="display: none;">
|
||||
<!-- 图表控制面板 -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-6">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5><i class="fas fa-chart-line me-2"></i>性能趋势</h5>
|
||||
<h5><i class="fas fa-chart-bar me-2"></i>数据分析控制面板</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="chart-container">
|
||||
<canvas id="analyticsChart"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5><i class="fas fa-chart-pie me-2"></i>类别分布</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="chart-container">
|
||||
<canvas id="categoryChart"></canvas>
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<label class="form-label">时间范围</label>
|
||||
<select class="form-select" id="timeRange">
|
||||
<option value="7">最近7天</option>
|
||||
<option value="30" selected>最近30天</option>
|
||||
<option value="90">最近90天</option>
|
||||
<option value="365">最近1年</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label class="form-label">图表类型</label>
|
||||
<select class="form-select" id="chartType">
|
||||
<option value="line">折线图</option>
|
||||
<option value="bar" selected>柱状图</option>
|
||||
<option value="pie">饼图</option>
|
||||
<option value="doughnut">环形图</option>
|
||||
<option value="radar">雷达图</option>
|
||||
<option value="polar">极坐标图</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label class="form-label">数据维度</label>
|
||||
<select class="form-select" id="dataDimension">
|
||||
<option value="workorders" selected>工单统计</option>
|
||||
<option value="alerts">预警统计</option>
|
||||
<option value="performance">性能指标</option>
|
||||
<option value="satisfaction">满意度分析</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label class="form-label">操作</label>
|
||||
<div class="d-grid">
|
||||
<button class="btn btn-primary" onclick="dashboard.updateCharts()">
|
||||
<i class="fas fa-sync-alt me-1"></i>刷新图表
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 主要图表区域 -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<h5><i class="fas fa-chart-line me-2"></i>主要趋势分析</h5>
|
||||
<div class="btn-group btn-group-sm" role="group">
|
||||
<button type="button" class="btn btn-outline-primary" onclick="dashboard.exportChart('mainChart')">
|
||||
<i class="fas fa-download me-1"></i>导出
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-secondary" onclick="dashboard.fullscreenChart('mainChart')">
|
||||
<i class="fas fa-expand me-1"></i>全屏
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="chart-container" style="position: relative; height: 400px;">
|
||||
<canvas id="mainChart"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5><i class="fas fa-chart-pie me-2"></i>分布分析</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="chart-container" style="position: relative; height: 300px;">
|
||||
<canvas id="distributionChart"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 详细统计卡片 -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-3">
|
||||
<div class="card text-center">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-center justify-content-center mb-2">
|
||||
<i class="fas fa-tasks fa-2x text-primary me-3"></i>
|
||||
<div>
|
||||
<h3 class="mb-0" id="totalWorkorders">0</h3>
|
||||
<small class="text-muted">总工单数</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress" style="height: 4px;">
|
||||
<div class="progress-bar bg-primary" role="progressbar" style="width: 100%"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card text-center">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-center justify-content-center mb-2">
|
||||
<i class="fas fa-exclamation-triangle fa-2x text-warning me-3"></i>
|
||||
<div>
|
||||
<h3 class="mb-0" id="openWorkorders">0</h3>
|
||||
<small class="text-muted">待处理</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress" style="height: 4px;">
|
||||
<div class="progress-bar bg-warning" role="progressbar" id="openProgress" style="width: 0%"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card text-center">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-center justify-content-center mb-2">
|
||||
<i class="fas fa-check-circle fa-2x text-success me-3"></i>
|
||||
<div>
|
||||
<h3 class="mb-0" id="resolvedWorkorders">0</h3>
|
||||
<small class="text-muted">已解决</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress" style="height: 4px;">
|
||||
<div class="progress-bar bg-success" role="progressbar" id="resolvedProgress" style="width: 0%"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card text-center">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-center justify-content-center mb-2">
|
||||
<i class="fas fa-star fa-2x text-info me-3"></i>
|
||||
<div>
|
||||
<h3 class="mb-0" id="avgSatisfaction">0</h3>
|
||||
<small class="text-muted">平均满意度</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress" style="height: 4px;">
|
||||
<div class="progress-bar bg-info" role="progressbar" id="satisfactionProgress" style="width: 0%"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 多维度分析图表 -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5><i class="fas fa-chart-area me-2"></i>时间趋势分析</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="chart-container" style="position: relative; height: 300px;">
|
||||
<canvas id="trendChart"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5><i class="fas fa-chart-bar me-2"></i>优先级分布</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="chart-container" style="position: relative; height: 300px;">
|
||||
<canvas id="priorityChart"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 详细分析报告 -->
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<h5><i class="fas fa-table me-2"></i>详细分析报告</h5>
|
||||
<div class="btn-group btn-group-sm" role="group">
|
||||
<button type="button" class="btn btn-outline-primary" onclick="dashboard.exportReport()">
|
||||
<i class="fas fa-file-excel me-1"></i>导出Excel
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-secondary" onclick="dashboard.printReport()">
|
||||
<i class="fas fa-print me-1"></i>打印报告
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div id="analytics-report">
|
||||
<div class="loading-spinner">
|
||||
<i class="fas fa-spinner fa-spin"></i>
|
||||
<div class="loading-spinner text-center">
|
||||
<i class="fas fa-spinner fa-spin fa-2x"></i>
|
||||
<p class="mt-2">正在生成分析报告...</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1074,6 +1249,118 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 工单导入模态框 -->
|
||||
<div class="modal fade" id="importWorkOrderModal" tabindex="-1">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">导入工单</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="alert alert-info">
|
||||
<i class="fas fa-info-circle me-2"></i>
|
||||
请先下载模板文件,按照模板格式填写工单信息,然后上传Excel文件进行导入。
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">选择Excel文件</label>
|
||||
<input type="file" class="form-control" id="excel-file-input" accept=".xlsx,.xls">
|
||||
<div class="form-text">支持 .xlsx 和 .xls 格式,文件大小不超过16MB</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<span>Excel文件列名说明:</span>
|
||||
<button class="btn btn-outline-primary btn-sm" onclick="dashboard.downloadTemplate()">
|
||||
<i class="fas fa-download me-1"></i>下载模板
|
||||
</button>
|
||||
</div>
|
||||
<div class="table-responsive mt-2">
|
||||
<table class="table table-sm table-bordered">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>列名</th>
|
||||
<th>说明</th>
|
||||
<th>必填</th>
|
||||
<th>示例</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>标题</td>
|
||||
<td>工单标题</td>
|
||||
<td><span class="badge bg-danger">是</span></td>
|
||||
<td>车辆无法启动</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>描述</td>
|
||||
<td>工单详细描述</td>
|
||||
<td><span class="badge bg-danger">是</span></td>
|
||||
<td>用户反映车辆无法正常启动</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>分类</td>
|
||||
<td>工单分类</td>
|
||||
<td><span class="badge bg-secondary">否</span></td>
|
||||
<td>技术问题</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>优先级</td>
|
||||
<td>工单优先级</td>
|
||||
<td><span class="badge bg-secondary">否</span></td>
|
||||
<td>high</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>状态</td>
|
||||
<td>工单状态</td>
|
||||
<td><span class="badge bg-secondary">否</span></td>
|
||||
<td>open</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>解决方案</td>
|
||||
<td>解决方案描述</td>
|
||||
<td><span class="badge bg-secondary">否</span></td>
|
||||
<td>检查电池和启动系统</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>满意度</td>
|
||||
<td>满意度评分(1-5)</td>
|
||||
<td><span class="badge bg-secondary">否</span></td>
|
||||
<td>5</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="import-progress" class="d-none">
|
||||
<div class="progress mb-3">
|
||||
<div class="progress-bar" role="progressbar" style="width: 0%"></div>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<i class="fas fa-spinner fa-spin me-2"></i>
|
||||
<span id="import-status">正在导入工单...</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="import-result" class="d-none">
|
||||
<div class="alert alert-success">
|
||||
<i class="fas fa-check-circle me-2"></i>
|
||||
<span id="import-success-message"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
|
||||
<button type="button" class="btn btn-primary" id="import-workorder-btn" onclick="dashboard.importWorkOrders()">
|
||||
<i class="fas fa-upload me-1"></i>开始导入
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 添加知识模态框 -->
|
||||
<div class="modal fade" id="addKnowledgeModal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
|
||||
@@ -166,11 +166,27 @@
|
||||
<div class="card mt-4">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<h5><i class="fas fa-cogs me-2"></i>预警规则管理</h5>
|
||||
<button class="btn btn-sm btn-primary" data-bs-toggle="modal" data-bs-target="#ruleModal">
|
||||
<i class="fas fa-plus me-1"></i>添加规则
|
||||
</button>
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-sm btn-primary" data-bs-toggle="modal" data-bs-target="#ruleModal">
|
||||
<i class="fas fa-plus me-1"></i>添加规则
|
||||
</button>
|
||||
<button class="btn btn-sm btn-success" data-bs-toggle="modal" data-bs-target="#presetModal">
|
||||
<i class="fas fa-magic me-1"></i>预设模板
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<!-- 预设规则卡片 -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<h6 class="text-muted mb-3">常用预警规则模板</h6>
|
||||
<div class="row" id="preset-rules">
|
||||
<!-- 预设规则卡片将在这里动态生成 -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 自定义规则列表 -->
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
@@ -377,6 +393,260 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 预设模板模态框 -->
|
||||
<div class="modal fade" id="presetModal" tabindex="-1">
|
||||
<div class="modal-dialog modal-xl">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">预警规则预设模板</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="row">
|
||||
<!-- 性能预警模板 -->
|
||||
<div class="col-md-6 mb-4">
|
||||
<h6 class="text-primary mb-3"><i class="fas fa-tachometer-alt me-2"></i>性能预警模板</h6>
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<div class="card preset-card" data-preset="response_time">
|
||||
<div class="card-body text-center">
|
||||
<i class="fas fa-clock fa-2x text-warning mb-2"></i>
|
||||
<h6>响应时间预警</h6>
|
||||
<p class="small text-muted">API响应时间超过阈值</p>
|
||||
<div class="preset-params">
|
||||
<span class="badge bg-warning">警告</span>
|
||||
<span class="badge bg-info">性能</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<div class="card preset-card" data-preset="cpu_usage">
|
||||
<div class="card-body text-center">
|
||||
<i class="fas fa-microchip fa-2x text-danger mb-2"></i>
|
||||
<h6>CPU使用率预警</h6>
|
||||
<p class="small text-muted">CPU使用率过高</p>
|
||||
<div class="preset-params">
|
||||
<span class="badge bg-danger">严重</span>
|
||||
<span class="badge bg-info">性能</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<div class="card preset-card" data-preset="memory_usage">
|
||||
<div class="card-body text-center">
|
||||
<i class="fas fa-memory fa-2x text-warning mb-2"></i>
|
||||
<h6>内存使用率预警</h6>
|
||||
<p class="small text-muted">内存使用率过高</p>
|
||||
<div class="preset-params">
|
||||
<span class="badge bg-warning">警告</span>
|
||||
<span class="badge bg-info">性能</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<div class="card preset-card" data-preset="disk_usage">
|
||||
<div class="card-body text-center">
|
||||
<i class="fas fa-hdd fa-2x text-danger mb-2"></i>
|
||||
<h6>磁盘使用率预警</h6>
|
||||
<p class="small text-muted">磁盘空间不足</p>
|
||||
<div class="preset-params">
|
||||
<span class="badge bg-danger">严重</span>
|
||||
<span class="badge bg-info">性能</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 业务预警模板 -->
|
||||
<div class="col-md-6 mb-4">
|
||||
<h6 class="text-success mb-3"><i class="fas fa-chart-line me-2"></i>业务预警模板</h6>
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<div class="card preset-card" data-preset="satisfaction_low">
|
||||
<div class="card-body text-center">
|
||||
<i class="fas fa-frown fa-2x text-warning mb-2"></i>
|
||||
<h6>满意度预警</h6>
|
||||
<p class="small text-muted">用户满意度低于阈值</p>
|
||||
<div class="preset-params">
|
||||
<span class="badge bg-warning">警告</span>
|
||||
<span class="badge bg-success">业务</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<div class="card preset-card" data-preset="workorder_high">
|
||||
<div class="card-body text-center">
|
||||
<i class="fas fa-tasks fa-2x text-danger mb-2"></i>
|
||||
<h6>工单积压预警</h6>
|
||||
<p class="small text-muted">待处理工单过多</p>
|
||||
<div class="preset-params">
|
||||
<span class="badge bg-danger">严重</span>
|
||||
<span class="badge bg-success">业务</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<div class="card preset-card" data-preset="error_rate_high">
|
||||
<div class="card-body text-center">
|
||||
<i class="fas fa-exclamation-triangle fa-2x text-danger mb-2"></i>
|
||||
<h6>错误率预警</h6>
|
||||
<p class="small text-muted">系统错误率过高</p>
|
||||
<div class="preset-params">
|
||||
<span class="badge bg-danger">严重</span>
|
||||
<span class="badge bg-success">业务</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<div class="card preset-card" data-preset="conversion_low">
|
||||
<div class="card-body text-center">
|
||||
<i class="fas fa-percentage fa-2x text-warning mb-2"></i>
|
||||
<h6>转化率预警</h6>
|
||||
<p class="small text-muted">用户转化率下降</p>
|
||||
<div class="preset-params">
|
||||
<span class="badge bg-warning">警告</span>
|
||||
<span class="badge bg-success">业务</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 系统预警模板 -->
|
||||
<div class="col-md-6 mb-4">
|
||||
<h6 class="text-info mb-3"><i class="fas fa-server me-2"></i>系统预警模板</h6>
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<div class="card preset-card" data-preset="service_down">
|
||||
<div class="card-body text-center">
|
||||
<i class="fas fa-power-off fa-2x text-danger mb-2"></i>
|
||||
<h6>服务宕机预警</h6>
|
||||
<p class="small text-muted">关键服务不可用</p>
|
||||
<div class="preset-params">
|
||||
<span class="badge bg-danger">严重</span>
|
||||
<span class="badge bg-info">系统</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<div class="card preset-card" data-preset="database_slow">
|
||||
<div class="card-body text-center">
|
||||
<i class="fas fa-database fa-2x text-warning mb-2"></i>
|
||||
<h6>数据库慢查询</h6>
|
||||
<p class="small text-muted">数据库查询过慢</p>
|
||||
<div class="preset-params">
|
||||
<span class="badge bg-warning">警告</span>
|
||||
<span class="badge bg-info">系统</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<div class="card preset-card" data-preset="network_latency">
|
||||
<div class="card-body text-center">
|
||||
<i class="fas fa-wifi fa-2x text-warning mb-2"></i>
|
||||
<h6>网络延迟预警</h6>
|
||||
<p class="small text-muted">网络延迟过高</p>
|
||||
<div class="preset-params">
|
||||
<span class="badge bg-warning">警告</span>
|
||||
<span class="badge bg-info">系统</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<div class="card preset-card" data-preset="api_error">
|
||||
<div class="card-body text-center">
|
||||
<i class="fas fa-bug fa-2x text-danger mb-2"></i>
|
||||
<h6>API错误预警</h6>
|
||||
<p class="small text-muted">API调用失败率过高</p>
|
||||
<div class="preset-params">
|
||||
<span class="badge bg-danger">严重</span>
|
||||
<span class="badge bg-info">系统</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 质量预警模板 -->
|
||||
<div class="col-md-6 mb-4">
|
||||
<h6 class="text-warning mb-3"><i class="fas fa-award me-2"></i>质量预警模板</h6>
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<div class="card preset-card" data-preset="code_quality">
|
||||
<div class="card-body text-center">
|
||||
<i class="fas fa-code fa-2x text-warning mb-2"></i>
|
||||
<h6>代码质量预警</h6>
|
||||
<p class="small text-muted">代码质量评分过低</p>
|
||||
<div class="preset-params">
|
||||
<span class="badge bg-warning">警告</span>
|
||||
<span class="badge bg-warning">质量</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<div class="card preset-card" data-preset="test_coverage">
|
||||
<div class="card-body text-center">
|
||||
<i class="fas fa-check-circle fa-2x text-info mb-2"></i>
|
||||
<h6>测试覆盖率预警</h6>
|
||||
<p class="small text-muted">测试覆盖率不足</p>
|
||||
<div class="preset-params">
|
||||
<span class="badge bg-info">信息</span>
|
||||
<span class="badge bg-warning">质量</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<div class="card preset-card" data-preset="security_scan">
|
||||
<div class="card-body text-center">
|
||||
<i class="fas fa-shield-alt fa-2x text-danger mb-2"></i>
|
||||
<h6>安全扫描预警</h6>
|
||||
<p class="small text-muted">发现安全漏洞</p>
|
||||
<div class="preset-params">
|
||||
<span class="badge bg-danger">严重</span>
|
||||
<span class="badge bg-warning">质量</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<div class="card preset-card" data-preset="performance_regression">
|
||||
<div class="card-body text-center">
|
||||
<i class="fas fa-chart-line fa-2x text-warning mb-2"></i>
|
||||
<h6>性能回归预警</h6>
|
||||
<p class="small text-muted">性能指标下降</p>
|
||||
<div class="preset-params">
|
||||
<span class="badge bg-warning">警告</span>
|
||||
<span class="badge bg-warning">质量</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 脚本 -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
|
||||
@@ -213,6 +213,19 @@ class WebSocketServer:
|
||||
|
||||
async def handle_client(self, websocket: WebSocketServerProtocol, path: str):
|
||||
"""处理客户端连接"""
|
||||
# 检查连接头
|
||||
headers = websocket.request_headers
|
||||
connection = headers.get("Connection", "").lower()
|
||||
|
||||
# 处理不同的连接头格式
|
||||
if "upgrade" not in connection and "keep-alive" in connection:
|
||||
logger.warning(f"收到非标准连接头: {connection}")
|
||||
# 对于keep-alive连接头,我们仍然接受连接
|
||||
elif "upgrade" not in connection:
|
||||
logger.warning(f"连接头不包含upgrade: {connection}")
|
||||
await websocket.close(code=1002, reason="Invalid connection header")
|
||||
return
|
||||
|
||||
await self.register_client(websocket)
|
||||
|
||||
try:
|
||||
@@ -220,6 +233,8 @@ class WebSocketServer:
|
||||
await self.handle_message(websocket, message)
|
||||
except websockets.exceptions.ConnectionClosed:
|
||||
pass
|
||||
except Exception as e:
|
||||
logger.error(f"WebSocket连接错误: {e}")
|
||||
finally:
|
||||
await self.unregister_client(websocket)
|
||||
|
||||
@@ -227,9 +242,48 @@ class WebSocketServer:
|
||||
"""启动WebSocket服务器"""
|
||||
logger.info(f"启动WebSocket服务器: ws://{self.host}:{self.port}")
|
||||
|
||||
async with websockets.serve(self.handle_client, self.host, self.port):
|
||||
# 添加CORS支持
|
||||
async def handle_client_with_cors(websocket: WebSocketServerProtocol, path: str):
|
||||
# 设置CORS头
|
||||
if websocket.request_headers.get("Origin"):
|
||||
# 允许跨域连接
|
||||
pass
|
||||
await self.handle_client(websocket, path)
|
||||
|
||||
async with websockets.serve(
|
||||
handle_client_with_cors,
|
||||
self.host,
|
||||
self.port,
|
||||
# 添加额外的服务器选项
|
||||
process_request=self._process_request
|
||||
):
|
||||
await asyncio.Future() # 保持服务器运行
|
||||
|
||||
def _process_request(self, path, request_headers):
|
||||
"""处理HTTP请求,支持CORS"""
|
||||
# 检查是否是WebSocket升级请求
|
||||
if request_headers.get("Upgrade", "").lower() == "websocket":
|
||||
return None # 允许WebSocket连接
|
||||
|
||||
# 对于非WebSocket请求,返回简单的HTML页面
|
||||
return (
|
||||
200,
|
||||
[("Content-Type", "text/html; charset=utf-8")],
|
||||
b"""
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>WebSocket Server</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>WebSocket Server is running</h1>
|
||||
<p>This is a WebSocket server. Please use a WebSocket client to connect.</p>
|
||||
<p>WebSocket URL: ws://localhost:8765</p>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
)
|
||||
|
||||
def run(self):
|
||||
"""运行服务器"""
|
||||
asyncio.run(self.start_server())
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
import sys
|
||||
import os
|
||||
import logging
|
||||
import threading
|
||||
import asyncio
|
||||
from datetime import datetime
|
||||
|
||||
# 添加项目根目录到Python路径
|
||||
@@ -23,6 +25,15 @@ def setup_logging():
|
||||
]
|
||||
)
|
||||
|
||||
def start_websocket_server():
|
||||
"""启动WebSocket服务器"""
|
||||
try:
|
||||
from src.web.websocket_server import WebSocketServer
|
||||
server = WebSocketServer(host="localhost", port=8765)
|
||||
server.run()
|
||||
except Exception as e:
|
||||
print(f"WebSocket服务器启动失败: {e}")
|
||||
|
||||
def main():
|
||||
"""主函数"""
|
||||
print("=" * 60)
|
||||
@@ -58,10 +69,15 @@ def main():
|
||||
print(" 主页: http://localhost:5000")
|
||||
print(" 预警管理: http://localhost:5000/alerts")
|
||||
print(" 实时对话: http://localhost:5000/chat")
|
||||
print(" WebSocket: ws://localhost:8765")
|
||||
print()
|
||||
print("按 Ctrl+C 停止服务")
|
||||
print("=" * 60)
|
||||
|
||||
# 在单独线程中启动WebSocket服务器
|
||||
websocket_thread = threading.Thread(target=start_websocket_server, daemon=True)
|
||||
websocket_thread.start()
|
||||
|
||||
# 启动Flask应用
|
||||
app.run(
|
||||
debug=False,
|
||||
|
||||
BIN
uploads/workorder_template.xlsx
Normal file
BIN
uploads/workorder_template.xlsx
Normal file
Binary file not shown.
Reference in New Issue
Block a user