调整为表格~~~
This commit is contained in:
@@ -151,8 +151,57 @@
|
||||
<div v-else>
|
||||
<div class="chart-container">
|
||||
<h3>消息数量趋势</h3>
|
||||
<!-- 直接在Vue模板中创建图表容器 -->
|
||||
<div ref="trendChartContainer" style="width: 100%; height: 300px;"></div>
|
||||
<!-- 使用Vue的条件渲染和循环来显示表格 -->
|
||||
<div v-if="trendData.dates && trendData.dates.length > 0">
|
||||
<table class="el-table" style="width: 100%;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="padding: 12px 0; text-align: center; background-color: #f5f7fa; color: #606266; font-weight: bold; border-bottom: 1px solid #ebeef5;">日期</th>
|
||||
<th style="padding: 12px 0; text-align: center; background-color: #f5f7fa; color: #606266; font-weight: bold; border-bottom: 1px solid #ebeef5;">消息数量</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="(date, index) in trendData.dates" :key="index">
|
||||
<td style="padding: 12px 0; text-align: center; border-bottom: 1px solid #ebeef5;">{{ date }}</td>
|
||||
<td style="padding: 12px 0; text-align: center; border-bottom: 1px solid #ebeef5;">
|
||||
{{ trendData.counts[index] }}
|
||||
<span style="color: #909399; font-size: 12px;">({{ getPercentage(index) }}%)</span>
|
||||
<div style="width: 100%; height: 6px; background-color: #f0f0f0; margin-top: 5px; border-radius: 3px;">
|
||||
<div style="height: 100%; background-color: #409EFF; border-radius: 3px;" :style="{ width: getPercentage(index) + '%' }"></div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding: 12px 0; text-align: center; border-bottom: 1px solid #ebeef5; font-weight: bold;">总计</td>
|
||||
<td style="padding: 12px 0; text-align: center; border-bottom: 1px solid #ebeef5; font-weight: bold;">{{ totalMessages }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div v-else style="text-align: center; padding: 20px;">暂无数据</div>
|
||||
|
||||
<!-- 统计摘要 -->
|
||||
<div v-if="trendData.dates && trendData.dates.length > 0" style="margin-top: 20px; padding: 15px; background-color: #f5f7fa; border-radius: 4px;">
|
||||
<h4 style="margin: 0 0 10px 0;">统计摘要</h4>
|
||||
<div style="display: flex; flex-wrap: wrap; gap: 15px;">
|
||||
<div style="flex: 1; min-width: 150px;">
|
||||
<div style="font-size: 12px; color: #909399;">总消息数</div>
|
||||
<div style="font-size: 18px; font-weight: bold; color: #303133;">{{ totalMessages }}</div>
|
||||
</div>
|
||||
<div style="flex: 1; min-width: 150px;">
|
||||
<div style="font-size: 12px; color: #909399;">日均消息数</div>
|
||||
<div style="font-size: 18px; font-weight: bold; color: #303133;">{{ avgMessages }}</div>
|
||||
</div>
|
||||
<div style="flex: 1; min-width: 150px;">
|
||||
<div style="font-size: 12px; color: #909399;">最高消息日</div>
|
||||
<div style="font-size: 18px; font-weight: bold; color: #303133;">{{ maxDay }} ({{ maxMessages }})</div>
|
||||
</div>
|
||||
<div style="flex: 1; min-width: 150px;">
|
||||
<div style="font-size: 12px; color: #909399;">最低消息日</div>
|
||||
<div style="font-size: 18px; font-weight: bold; color: #303133;">{{ minDay }} ({{ minMessages }})</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin-top: 20px; text-align: center;">
|
||||
<el-radio-group v-model="trendDays" @change="loadMessageTrend">
|
||||
@@ -195,7 +244,10 @@
|
||||
trendDialogVisible: false,
|
||||
trendLoading: false,
|
||||
trendDays: 7,
|
||||
charts: {} // 使用charts对象存储图表实例
|
||||
trendData: {
|
||||
dates: [],
|
||||
counts: []
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -206,6 +258,30 @@
|
||||
(group.group_id && group.group_id.toLowerCase().includes(query)) ||
|
||||
(group.group_name && group.group_name.toLowerCase().includes(query))
|
||||
);
|
||||
},
|
||||
// 计算属性用于趋势数据
|
||||
totalMessages() {
|
||||
return this.trendData.counts.reduce((sum, count) => sum + parseInt(count || 0), 0);
|
||||
},
|
||||
avgMessages() {
|
||||
return this.trendData.dates.length > 0 ?
|
||||
(this.totalMessages / this.trendData.dates.length).toFixed(2) : 0;
|
||||
},
|
||||
maxMessages() {
|
||||
return this.trendData.counts.length > 0 ?
|
||||
Math.max(...this.trendData.counts.map(c => parseInt(c || 0))) : 0;
|
||||
},
|
||||
minMessages() {
|
||||
return this.trendData.counts.length > 0 ?
|
||||
Math.min(...this.trendData.counts.map(c => parseInt(c || 0))) : 0;
|
||||
},
|
||||
maxDay() {
|
||||
const maxIndex = this.trendData.counts.indexOf(this.maxMessages.toString());
|
||||
return maxIndex >= 0 ? this.trendData.dates[maxIndex] : '';
|
||||
},
|
||||
minDay() {
|
||||
const minIndex = this.trendData.counts.indexOf(this.minMessages.toString());
|
||||
return minIndex >= 0 ? this.trendData.dates[minIndex] : '';
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
@@ -426,8 +502,9 @@
|
||||
// 对话框打开后的回调
|
||||
onTrendDialogOpened() {
|
||||
console.log('对话框已打开');
|
||||
// 直接加载数据,不使用延迟
|
||||
this.loadMessageTrend();
|
||||
this.$nextTick(() => {
|
||||
this.loadMessageTrend();
|
||||
});
|
||||
},
|
||||
|
||||
loadMessageTrend() {
|
||||
@@ -436,8 +513,8 @@
|
||||
axios.get(`/api/robot/group/${this.currentGroupId}/message_trend?days=${this.trendDays}`)
|
||||
.then(response => {
|
||||
if (response.data.success) {
|
||||
// 直接渲染表格显示数据
|
||||
this.renderTrendTable(response.data.data);
|
||||
// 直接更新数据,让Vue的响应式系统处理渲染
|
||||
this.trendData = response.data.data || { dates: [], counts: [] };
|
||||
this.trendLoading = false;
|
||||
} else {
|
||||
this.$message.error('加载消息趋势失败');
|
||||
@@ -451,126 +528,14 @@
|
||||
});
|
||||
},
|
||||
|
||||
renderTrendTable(data) {
|
||||
try {
|
||||
console.log('开始渲染趋势数据');
|
||||
|
||||
// 获取容器元素
|
||||
const container = this.$refs.trendChartContainer;
|
||||
|
||||
if (!container) {
|
||||
console.error('找不到图表容器');
|
||||
this.$message.error('无法找到图表容器,请尝试重新打开对话框');
|
||||
return;
|
||||
}
|
||||
|
||||
// 准备数据
|
||||
const labels = data.dates || [];
|
||||
const messageData = (data.counts || []).map(count => parseInt(count) || 0);
|
||||
|
||||
if (labels.length === 0) {
|
||||
container.innerHTML = '<div style="text-align: center; padding: 20px;">暂无数据</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
// 销毁之前的图表实例(如果存在)
|
||||
if (this.charts.trendChart) {
|
||||
this.charts.trendChart.destroy();
|
||||
}
|
||||
|
||||
// 创建canvas元素
|
||||
container.innerHTML = '<canvas id="messageChart" width="100%" height="300"></canvas>';
|
||||
const ctx = document.getElementById('messageChart').getContext('2d');
|
||||
|
||||
// 使用Chart.js创建图表
|
||||
this.charts.trendChart = new Chart(ctx, {
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: labels,
|
||||
datasets: [{
|
||||
label: '消息数量',
|
||||
data: messageData,
|
||||
backgroundColor: 'rgba(75, 192, 192, 0.5)',
|
||||
borderColor: 'rgba(75, 192, 192, 1)',
|
||||
borderWidth: 1
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
scales: {
|
||||
y: {
|
||||
beginAtZero: true,
|
||||
title: {
|
||||
display: true,
|
||||
text: '消息数量'
|
||||
}
|
||||
},
|
||||
x: {
|
||||
title: {
|
||||
display: true,
|
||||
text: '日期'
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
title: {
|
||||
display: true,
|
||||
text: '群组消息数量趋势',
|
||||
font: {
|
||||
size: 16
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
callbacks: {
|
||||
label: function(context) {
|
||||
return `消息数量: ${context.raw}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 添加表格显示详细数据
|
||||
let tableHtml = `
|
||||
<div style="margin-top: 20px;">
|
||||
<h4 style="margin: 10px 0;">详细数据</h4>
|
||||
<table class="el-table" style="width: 100%;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="padding: 12px 0; text-align: center; background-color: #f5f7fa; color: #606266; font-weight: bold; border-bottom: 1px solid #ebeef5;">日期</th>
|
||||
<th style="padding: 12px 0; text-align: center; background-color: #f5f7fa; color: #606266; font-weight: bold; border-bottom: 1px solid #ebeef5;">消息数量</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
`;
|
||||
|
||||
for (let i = 0; i < labels.length; i++) {
|
||||
tableHtml += `
|
||||
<tr>
|
||||
<td style="padding: 12px 0; text-align: center; border-bottom: 1px solid #ebeef5;">${labels[i]}</td>
|
||||
<td style="padding: 12px 0; text-align: center; border-bottom: 1px solid #ebeef5;">${messageData[i]}</td>
|
||||
</tr>
|
||||
`;
|
||||
}
|
||||
|
||||
tableHtml += `
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// 在图表下方添加表格
|
||||
const tableContainer = document.createElement('div');
|
||||
tableContainer.innerHTML = tableHtml;
|
||||
container.parentNode.insertBefore(tableContainer, container.nextSibling);
|
||||
|
||||
} catch (error) {
|
||||
console.error('渲染趋势数据出错:', error);
|
||||
this.$message.error('渲染趋势数据出错: ' + error.message);
|
||||
}
|
||||
// 计算百分比的方法
|
||||
getPercentage(index) {
|
||||
const count = parseInt(this.trendData.counts[index] || 0);
|
||||
return this.totalMessages > 0 ?
|
||||
((count / this.totalMessages) * 100).toFixed(2) : 0;
|
||||
}
|
||||
|
||||
// ... 保留其他方法 ...
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user