新增消息趋势分析
This commit is contained in:
@@ -92,3 +92,39 @@ def get_groups():
|
||||
except Exception as e:
|
||||
logger.error(f"获取群组列表失败: {e}")
|
||||
return jsonify({'error': str(e)}), 500
|
||||
|
||||
|
||||
@messages_bp.route('/api/hourly_message_trend', methods=['GET'])
|
||||
@login_required
|
||||
def get_hourly_message_trend():
|
||||
"""获取按小时聊天趋势数据API"""
|
||||
try:
|
||||
server = current_app.dashboard_server
|
||||
# 获取查询参数
|
||||
group_id = request.args.get('group_id')
|
||||
days = int(request.args.get('days', 1))
|
||||
|
||||
# 调用数据库方法获取按小时消息趋势数据
|
||||
trend_data = server.message_storage.get_hourly_message_trend(group_id=group_id, days=days)
|
||||
|
||||
# 格式化数据为前端需要的格式
|
||||
hours = []
|
||||
counts = []
|
||||
for item in trend_data:
|
||||
hours.append(item['hour_slot'])
|
||||
counts.append(item['message_count'])
|
||||
|
||||
# 获取群组名称
|
||||
group_name = server.contact_manager.get_nickname(group_id) if group_id else "所有群组"
|
||||
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'data': {
|
||||
'hours': hours,
|
||||
'counts': counts,
|
||||
'group_name': group_name
|
||||
}
|
||||
})
|
||||
except Exception as e:
|
||||
logger.error(f"获取按小时聊天趋势数据失败: {e}")
|
||||
return jsonify({'success': False, 'error': str(e)}), 500
|
||||
@@ -143,6 +143,29 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- 添加一个新行用于显示按小时聊天趋势图 -->
|
||||
<el-row :gutter="20" style="margin-top: 20px;">
|
||||
<el-col :span="24">
|
||||
<el-card shadow="hover" v-loading="hourlyMessageTrendLoading">
|
||||
<div slot="header" style="display: flex; justify-content: space-between; align-items: center;">
|
||||
<span>按小时聊天趋势</span>
|
||||
<div style="display: flex; align-items: center;">
|
||||
<el-select v-model="selectedGroupForHourlyTrend" placeholder="选择群组" style="width: 200px; margin-right: 10px;" @change="loadHourlyMessageTrend">
|
||||
<el-option v-for="group in groups" :key="group.group_id" :label="group.group_name" :value="group.group_id"></el-option>
|
||||
</el-select>
|
||||
<el-select v-model="hourlyTrendDays" placeholder="选择时间范围" style="width: 120px;" @change="loadHourlyMessageTrend">
|
||||
<el-option :value="1" label="最近1天"></el-option>
|
||||
<el-option :value="2" label="最近2天"></el-option>
|
||||
<el-option :value="3" label="最近3天"></el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="chart-container">
|
||||
<canvas id="hourlyMessageTrendChart" height="200"></canvas>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<!-- 系统状态卡片移到顶部 -->
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24">
|
||||
@@ -261,6 +284,23 @@
|
||||
disk_usage: 0,
|
||||
uptime: 0,
|
||||
timestamp: '-'
|
||||
},
|
||||
groups: [],
|
||||
selectedGroupForHourlyTrend: '',
|
||||
hourlyTrendDays: 1,
|
||||
hourlyMessageTrendData: {
|
||||
hours: [],
|
||||
counts: []
|
||||
},
|
||||
hourlyMessageTrendLoading: true,
|
||||
charts: {
|
||||
pluginChart: null,
|
||||
successRateChart: null,
|
||||
trendChart: null,
|
||||
cpuChart: null,
|
||||
memoryChart: null,
|
||||
diskChart: null,
|
||||
hourlyMessageTrendChart: null // 添加这一行
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -287,6 +327,7 @@
|
||||
this.loadSystemInfo();
|
||||
// 加载当前用户信息
|
||||
this.loadCurrentUserInfo();
|
||||
this.loadGroups(); // 添加这一行
|
||||
// 设置定时刷新系统信息(每30秒)
|
||||
this.systemInfoTimer = setInterval(this.loadSystemInfo, 30000);
|
||||
},
|
||||
@@ -598,6 +639,87 @@
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
loadGroups() {
|
||||
axios.get('/api/groups')
|
||||
.then(response => {
|
||||
if (response.data && response.data.groups) {
|
||||
this.groups = response.data.groups;
|
||||
if (this.groups.length > 0) {
|
||||
this.selectedGroupForHourlyTrend = this.groups[0].group_id;
|
||||
this.loadHourlyMessageTrend();
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('加载群组列表失败:', error);
|
||||
this.$message.error('加载群组列表失败');
|
||||
});
|
||||
},
|
||||
loadHourlyMessageTrend() {
|
||||
if (!this.selectedGroupForHourlyTrend) return;
|
||||
|
||||
this.hourlyMessageTrendLoading = true;
|
||||
axios.get('/api/hourly_message_trend', {
|
||||
params: {
|
||||
group_id: this.selectedGroupForHourlyTrend,
|
||||
days: this.hourlyTrendDays
|
||||
}
|
||||
})
|
||||
.then(response => {
|
||||
if (response.data && response.data.success) {
|
||||
this.hourlyMessageTrendData = response.data.data;
|
||||
this.$nextTick(() => {
|
||||
this.renderHourlyMessageTrendChart();
|
||||
});
|
||||
} else {
|
||||
this.$message.error(response.data.error || '加载按小时聊天趋势数据失败');
|
||||
}
|
||||
this.hourlyMessageTrendLoading = false;
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('加载按小时聊天趋势数据失败:', error);
|
||||
this.$message.error('加载按小时聊天趋势数据失败');
|
||||
this.hourlyMessageTrendLoading = false;
|
||||
});
|
||||
},
|
||||
renderHourlyMessageTrendChart() {
|
||||
const ctx = document.getElementById('hourlyMessageTrendChart').getContext('2d');
|
||||
|
||||
// 销毁旧图表
|
||||
if (this.charts.hourlyMessageTrendChart) {
|
||||
this.charts.hourlyMessageTrendChart.destroy();
|
||||
}
|
||||
|
||||
// 创建新图表
|
||||
this.charts.hourlyMessageTrendChart = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: this.hourlyMessageTrendData.hours,
|
||||
datasets: [{
|
||||
label: '消息数量',
|
||||
data: this.hourlyMessageTrendData.counts,
|
||||
fill: false,
|
||||
backgroundColor: 'rgba(255, 99, 132, 0.6)',
|
||||
borderColor: 'rgba(255, 99, 132, 1)',
|
||||
tension: 0.1
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
scales: {
|
||||
y: {
|
||||
beginAtZero: true
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
title: {
|
||||
display: true,
|
||||
text: `${this.hourlyMessageTrendData.group_name || '未知群组'} 的聊天趋势`
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -208,3 +208,37 @@ class MessageStorageDB(BaseDBOperator):
|
||||
# 使用已有的日志记录方式
|
||||
print(f"更新消息图片路径出错: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def get_hourly_message_trend(self, group_id: str = None, days: int = 1) -> List[Dict]:
|
||||
"""获取指定群组的按小时消息趋势数据
|
||||
|
||||
Args:
|
||||
group_id: 群组ID,如果为None则获取所有群组的数据
|
||||
days: 获取最近几天的数据,默认1天
|
||||
|
||||
Returns:
|
||||
包含小时和消息数量的列表
|
||||
"""
|
||||
sql = """
|
||||
SELECT
|
||||
DATE_FORMAT(timestamp, '%Y-%m-%d %H:00') as hour_slot,
|
||||
COUNT(*) as message_count
|
||||
FROM messages
|
||||
WHERE timestamp >= DATE_SUB(NOW(), INTERVAL %s DAY)
|
||||
"""
|
||||
|
||||
params = [days]
|
||||
|
||||
# 如果指定了群组ID,则添加群组筛选条件
|
||||
if group_id:
|
||||
sql += "AND group_id = %s "
|
||||
params.append(group_id)
|
||||
|
||||
# 按小时分组并排序
|
||||
sql += """
|
||||
GROUP BY hour_slot
|
||||
ORDER BY hour_slot
|
||||
"""
|
||||
|
||||
return self.execute_query(sql, tuple(params)) or []
|
||||
|
||||
Reference in New Issue
Block a user