调整趋势图功能,加入了查询数据库,分析群聊聊天数量的功能

This commit is contained in:
liuwei
2025-03-26 13:41:07 +08:00
parent e83ea9c108
commit 65269e6f12
3 changed files with 185 additions and 5 deletions

View File

@@ -85,3 +85,26 @@ class MessageStorageDB(BaseDBOperator):
""" """
params = (group_id, wx_id, date, count) params = (group_id, wx_id, date, count)
return self.execute_update(sql, params) return self.execute_update(sql, params)
def get_message_trend(self, group_id: str, days: int = 7) -> List[Dict]:
"""获取指定群组的消息趋势数据
Args:
group_id: 群组ID
days: 获取最近几天的数据默认7天
Returns:
包含日期和消息数量的列表
"""
sql = """
SELECT
DATE(timestamp) as date,
COUNT(*) as message_count
FROM messages
WHERE group_id = %s
AND timestamp >= DATE_SUB(CURDATE(), INTERVAL %s DAY)
GROUP BY DATE(timestamp)
ORDER BY date
"""
return self.execute_query(sql, (group_id, days)) or []

View File

@@ -1,11 +1,13 @@
import logging import logging
from typing import Dict, Any, Optional
import threading import threading
import time import time
import os import os
from datetime import datetime
from flask import Flask, render_template, request, jsonify, redirect, url_for, session, send_from_directory from flask import Flask, render_template, request, jsonify, redirect, url_for, session, send_from_directory
from db.connection import DBConnectionManager from db.connection import DBConnectionManager
from db.message_storage import MessageStorageDB
from db.stats_db import StatsDBOperator from db.stats_db import StatsDBOperator
from utils.wechat.contact_manager import ContactManager from utils.wechat.contact_manager import ContactManager
from robot_cmd.robot_command import GroupBotManager, Feature, PermissionStatus from robot_cmd.robot_command import GroupBotManager, Feature, PermissionStatus
@@ -24,6 +26,7 @@ class DashboardServer:
# 修正:使用单例模式获取数据库连接 # 修正:使用单例模式获取数据库连接
self.db_manager = DBConnectionManager.get_instance() self.db_manager = DBConnectionManager.get_instance()
self.stats_db = StatsDBOperator(self.db_manager) self.stats_db = StatsDBOperator(self.db_manager)
self.message_storage = MessageStorageDB(self.db_manager)
# 获取联系人管理器实例 # 获取联系人管理器实例
self.contact_manager = ContactManager.get_instance() self.contact_manager = ContactManager.get_instance()
self.app = self._create_app() self.app = self._create_app()
@@ -286,6 +289,40 @@ class DashboardServer:
self.logger.info(f"看板主页/api/plugin_trend: {trend}") self.logger.info(f"看板主页/api/plugin_trend: {trend}")
return jsonify({"success": True, "data": trend}) return jsonify({"success": True, "data": trend})
@app.route('/api/robot/group/<group_id>/message_trend', methods=['GET'])
def get_group_message_trend(group_id):
"""获取群组消息趋势数据"""
try:
days = request.args.get('days', default=7, type=int)
# 获取消息存储实例
trend_data = self.message_storage.get_message_trend(group_id, days)
# 格式化数据为前端需要的格式
dates = []
counts = []
for item in trend_data:
# 将日期转换为字符串
if isinstance(item['date'], datetime):
date_str = item['date'].strftime('%Y-%m-%d')
else:
date_str = str(item['date'])
dates.append(date_str)
counts.append(item['message_count'])
return jsonify({
'success': True,
'data': {
'dates': dates,
'counts': counts
}
})
except Exception as e:
return jsonify({
'success': False,
'error': str(e)
})
return app return app
def run(self) -> None: def run(self) -> None:

View File

@@ -45,7 +45,7 @@
</el-tag> </el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="操作" width="200"> <el-table-column label="操作" width="280">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button <el-button
size="mini" size="mini"
@@ -59,6 +59,12 @@
@click="toggleRobotStatus(scope.row)"> @click="toggleRobotStatus(scope.row)">
{% raw %}{{ scope.row.robot_status === 'enabled' ? '关闭' : '启用' }}{% endraw %} {% raw %}{{ scope.row.robot_status === 'enabled' ? '关闭' : '启用' }}{% endraw %}
</el-button> </el-button>
<el-button
size="mini"
type="info"
@click="viewMessageTrend(scope.row)">
消息趋势
</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@@ -130,6 +136,27 @@
<el-button type="primary" @click="submitAddGroup">确定</el-button> <el-button type="primary" @click="submitAddGroup">确定</el-button>
</span> </span>
</el-dialog> </el-dialog>
<!-- 群组消息趋势图对话框 -->
<el-dialog
:title="currentGroupName + ' 消息趋势'"
:visible.sync="trendDialogVisible"
width="70%">
<div v-if="trendLoading" style="text-align: center; padding: 20px;">
<i class="el-icon-loading"></i>
<p>加载中...</p>
</div>
<div v-else>
<canvas id="messageTrendChart" style="width: 100%; height: 400px;"></canvas>
<div style="margin-top: 20px; text-align: center;">
<el-radio-group v-model="trendDays" @change="loadMessageTrend">
<el-radio-button :label="7">最近7天</el-radio-button>
<el-radio-button :label="14">最近14天</el-radio-button>
<el-radio-button :label="30">最近30天</el-radio-button>
</el-radio-group>
</div>
</div>
</el-dialog>
</div> </div>
{% endblock %} {% endblock %}
@@ -157,7 +184,12 @@
{ required: true, message: '请输入群组ID', trigger: 'blur' }, { required: true, message: '请输入群组ID', trigger: 'blur' },
{ pattern: /^\S+$/, message: '群组ID不能包含空格', trigger: 'blur' } { pattern: /^\S+$/, message: '群组ID不能包含空格', trigger: 'blur' }
] ]
} },
// 趋势图相关数据
trendDialogVisible: false,
trendLoading: false,
trendDays: 7,
trendChart: null
} }
}, },
computed: { computed: {
@@ -481,6 +513,94 @@
this.$message.error('批量移除失败: ' + error.message); this.$message.error('批量移除失败: ' + error.message);
}); });
}).catch(() => {}); }).catch(() => {});
},
// 查看消息趋势
viewMessageTrend(group) {
this.currentGroupId = group.group_id;
this.currentGroupName = group.group_name || group.group_id;
this.trendDialogVisible = true;
this.loadMessageTrend();
},
loadMessageTrend() {
this.trendLoading = true;
axios.get(`/api/robot/group/${this.currentGroupId}/message_trend?days=${this.trendDays}`)
.then(response => {
if (response.data.success) {
this.renderTrendChart(response.data.data);
} else {
this.$message.error('加载消息趋势失败');
}
this.trendLoading = false;
})
.catch(error => {
console.error('加载消息趋势失败:', error);
this.$message.error('加载消息趋势失败: ' + error.message);
this.trendLoading = false;
});
},
renderTrendChart(data) {
// 确保DOM元素已经渲染
this.$nextTick(() => {
// 如果已有图表,先销毁
if (this.trendChart) {
this.trendChart.destroy();
}
// 获取canvas元素
const ctx = document.getElementById('messageTrendChart').getContext('2d');
// 创建新图表
this.trendChart = new Chart(ctx, {
type: 'line',
data: {
labels: data.dates,
datasets: [{
label: '消息数量',
data: data.counts,
backgroundColor: 'rgba(75, 192, 192, 0.2)',
borderColor: 'rgba(75, 192, 192, 1)',
borderWidth: 2,
tension: 0.3,
fill: true
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
title: {
display: true,
text: '群聊消息数量趋势'
},
tooltip: {
mode: 'index',
intersect: false
},
legend: {
position: 'top',
}
},
scales: {
y: {
beginAtZero: true,
title: {
display: true,
text: '消息数量'
}
},
x: {
ticks: {
maxRotation: 45,
minRotation: 45
}
}
}
}
});
});
} }
} }
}); });