fix: 修复app.py中的缩进错误和logger配置问题
This commit is contained in:
131
src/web/app.py
131
src/web/app.py
@@ -10,6 +10,9 @@ import os
|
|||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
|
||||||
|
# 配置日志
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from openpyxl import Workbook
|
from openpyxl import Workbook
|
||||||
from openpyxl.styles import Font
|
from openpyxl.styles import Font
|
||||||
@@ -631,9 +634,9 @@ def get_workorders():
|
|||||||
priority_filter = request.args.get('priority')
|
priority_filter = request.args.get('priority')
|
||||||
with db_manager.get_session() as session:
|
with db_manager.get_session() as session:
|
||||||
q = session.query(WorkOrder)
|
q = session.query(WorkOrder)
|
||||||
if status_filter and status_filter != 'all':
|
if status_filter and status_filter != 'all':
|
||||||
q = q.filter(WorkOrder.status == status_filter)
|
q = q.filter(WorkOrder.status == status_filter)
|
||||||
if priority_filter and priority_filter != 'all':
|
if priority_filter and priority_filter != 'all':
|
||||||
q = q.filter(WorkOrder.priority == priority_filter)
|
q = q.filter(WorkOrder.priority == priority_filter)
|
||||||
q = q.order_by(WorkOrder.created_at.desc())
|
q = q.order_by(WorkOrder.created_at.desc())
|
||||||
rows = q.all()
|
rows = q.all()
|
||||||
@@ -877,80 +880,80 @@ def generate_db_analytics(days: int, dimension: str) -> dict:
|
|||||||
} for d in day_keys]
|
} for d in day_keys]
|
||||||
|
|
||||||
# 工单统计
|
# 工单统计
|
||||||
total = len(workorders)
|
total = len(workorders)
|
||||||
status_counts = Counter([wo.status for wo in workorders])
|
status_counts = Counter([wo.status for wo in workorders])
|
||||||
category_counts = Counter([wo.category for wo in workorders])
|
category_counts = Counter([wo.category for wo in workorders])
|
||||||
priority_counts = Counter([wo.priority for wo in workorders])
|
priority_counts = Counter([wo.priority for wo in workorders])
|
||||||
resolved_count = status_counts.get('resolved', 0)
|
resolved_count = status_counts.get('resolved', 0)
|
||||||
workorders_stats = {
|
workorders_stats = {
|
||||||
'total': total,
|
'total': total,
|
||||||
'open': status_counts.get('open', 0),
|
'open': status_counts.get('open', 0),
|
||||||
'in_progress': status_counts.get('in_progress', 0),
|
'in_progress': status_counts.get('in_progress', 0),
|
||||||
'resolved': resolved_count,
|
'resolved': resolved_count,
|
||||||
'closed': status_counts.get('closed', 0),
|
'closed': status_counts.get('closed', 0),
|
||||||
'by_category': dict(category_counts),
|
'by_category': dict(category_counts),
|
||||||
'by_priority': dict(priority_counts)
|
'by_priority': dict(priority_counts)
|
||||||
}
|
}
|
||||||
|
|
||||||
# 满意度
|
# 满意度
|
||||||
scores = []
|
scores = []
|
||||||
for wo in workorders:
|
for wo in workorders:
|
||||||
if wo.satisfaction_score not in (None, ''):
|
if wo.satisfaction_score not in (None, ''):
|
||||||
try:
|
try:
|
||||||
score = float(wo.satisfaction_score)
|
score = float(wo.satisfaction_score)
|
||||||
scores.append(score)
|
scores.append(score)
|
||||||
except (ValueError, TypeError):
|
except (ValueError, TypeError):
|
||||||
continue
|
continue
|
||||||
avg_satisfaction = round(sum(scores)/len(scores), 1) if scores else 0
|
avg_satisfaction = round(sum(scores)/len(scores), 1) if scores else 0
|
||||||
dist = Counter([str(int(round(s))) for s in scores]) if scores else {}
|
dist = Counter([str(int(round(s))) for s in scores]) if scores else {}
|
||||||
satisfaction_stats = {
|
satisfaction_stats = {
|
||||||
'average': avg_satisfaction,
|
'average': avg_satisfaction,
|
||||||
'distribution': {k: int(v) for k, v in dist.items()}
|
'distribution': {k: int(v) for k, v in dist.items()}
|
||||||
}
|
}
|
||||||
|
|
||||||
# 预警统计
|
# 预警统计
|
||||||
level_counts = Counter([al.level for al in alerts])
|
level_counts = Counter([al.level for al in alerts])
|
||||||
active_alerts = len([al for al in alerts if al.is_active])
|
active_alerts = len([al for al in alerts if al.is_active])
|
||||||
resolved_alerts = len([al for al in alerts if not al.is_active and al.resolved_at])
|
resolved_alerts = len([al for al in alerts if not al.is_active and al.resolved_at])
|
||||||
alerts_stats = {
|
alerts_stats = {
|
||||||
'total': len(alerts),
|
'total': len(alerts),
|
||||||
'active': active_alerts,
|
'active': active_alerts,
|
||||||
'resolved': resolved_alerts,
|
'resolved': resolved_alerts,
|
||||||
'by_level': {k: int(v) for k, v in level_counts.items()}
|
'by_level': {k: int(v) for k, v in level_counts.items()}
|
||||||
}
|
}
|
||||||
|
|
||||||
# 性能指标(基于对话响应时间粗略估计)
|
# 性能指标(基于对话响应时间粗略估计)
|
||||||
resp_times = []
|
resp_times = []
|
||||||
for c in conversations:
|
for c in conversations:
|
||||||
if c.response_time not in (None, ''):
|
if c.response_time not in (None, ''):
|
||||||
try:
|
try:
|
||||||
resp_time = float(c.response_time)
|
resp_time = float(c.response_time)
|
||||||
resp_times.append(resp_time)
|
resp_times.append(resp_time)
|
||||||
except (ValueError, TypeError):
|
except (ValueError, TypeError):
|
||||||
continue
|
continue
|
||||||
avg_resp = round(sum(resp_times)/len(resp_times), 2) if resp_times else 0
|
avg_resp = round(sum(resp_times)/len(resp_times), 2) if resp_times else 0
|
||||||
throughput = len(conversations) # 期间内的对话数量
|
throughput = len(conversations) # 期间内的对话数量
|
||||||
# 错误率:用严重预警比例粗估
|
# 错误率:用严重预警比例粗估
|
||||||
critical = level_counts.get('critical', 0)
|
critical = level_counts.get('critical', 0)
|
||||||
error_rate = round((critical / alerts_stats['total']) * 100, 2) if alerts_stats['total'] > 0 else 0
|
error_rate = round((critical / alerts_stats['total']) * 100, 2) if alerts_stats['total'] > 0 else 0
|
||||||
performance_stats = {
|
performance_stats = {
|
||||||
'response_time': avg_resp,
|
'response_time': avg_resp,
|
||||||
'uptime': 99.0, # 可接入真实监控后更新
|
'uptime': 99.0, # 可接入真实监控后更新
|
||||||
'error_rate': error_rate,
|
'error_rate': error_rate,
|
||||||
'throughput': throughput
|
'throughput': throughput
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'trend': trend,
|
'trend': trend,
|
||||||
'workorders': workorders_stats,
|
'workorders': workorders_stats,
|
||||||
'satisfaction': satisfaction_stats,
|
'satisfaction': satisfaction_stats,
|
||||||
'alerts': alerts_stats,
|
'alerts': alerts_stats,
|
||||||
'performance': performance_stats,
|
'performance': performance_stats,
|
||||||
'summary': {
|
'summary': {
|
||||||
'total_workorders': total,
|
'total_workorders': total,
|
||||||
'resolution_rate': round((resolved_count/total)*100, 1) if total > 0 else 0,
|
'resolution_rate': round((resolved_count/total)*100, 1) if total > 0 else 0,
|
||||||
'avg_satisfaction': avg_satisfaction,
|
'avg_satisfaction': avg_satisfaction,
|
||||||
'active_alerts': active_alerts
|
'active_alerts': active_alerts
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1144,11 +1147,11 @@ def get_settings():
|
|||||||
settings['api_key'] = '******'
|
settings['api_key'] = '******'
|
||||||
settings['api_key_masked'] = True
|
settings['api_key_masked'] = True
|
||||||
else:
|
else:
|
||||||
settings = {
|
settings = {
|
||||||
"api_timeout": 30,
|
"api_timeout": 30,
|
||||||
"max_history": 10,
|
"max_history": 10,
|
||||||
"refresh_interval": 10,
|
"refresh_interval": 10,
|
||||||
"auto_monitoring": True,
|
"auto_monitoring": True,
|
||||||
"agent_mode": True,
|
"agent_mode": True,
|
||||||
# LLM与API配置(仅持久化,不直接热更新LLM客户端)
|
# LLM与API配置(仅持久化,不直接热更新LLM客户端)
|
||||||
"api_provider": "openai",
|
"api_provider": "openai",
|
||||||
|
|||||||
Reference in New Issue
Block a user