新增消息趋势分析

This commit is contained in:
liuwei
2025-05-29 09:03:48 +08:00
parent 3c08352dd9
commit b93d217101
3 changed files with 192 additions and 0 deletions

View File

@@ -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

View File

@@ -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 || '未知群组'} 的聊天趋势`
}
}
}
});
}
}
});

View File

@@ -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 []