Files
abot/admin/dashboard/templates/robot_management.html

473 lines
20 KiB
HTML

{% extends "base.html" %}
{% block title %}群机器人管理 - 机器人管理后台{% endblock %}
{% block content %}
<!-- 群机器人管理 -->
<div>
<el-row :gutter="20">
<el-col :span="24">
<el-card shadow="hover">
<div slot="header" class="clearfix">
<span>群机器人管理</span>
<el-button
type="primary"
size="small"
style="float: right; margin-left: 10px;"
@click="showAddGroupDialog">
添加群组
</el-button>
<el-input
placeholder="搜索群组..."
v-model="searchQuery"
style="width: 200px; float: right"
clearable>
</el-input>
</div>
<!-- 群组列表 -->
<el-table
:data="filteredGroups"
style="width: 100%"
border
@selection-change="handleSelectionChange">
<el-table-column type="selection" width="55"></el-table-column>
<el-table-column label="群组信息">
<template slot-scope="scope">
{% raw %}{{ scope.row.group_name || scope.row.group_id }} ({{ scope.row.group_id }}){% endraw %}
</template>
</el-table-column>
<el-table-column label="机器人状态" width="120">
<template slot-scope="scope">
<el-tag
:type="scope.row.robot_status === 'enabled' ? 'success' : 'danger'">
{% raw %}{{ scope.row.robot_status === 'enabled' ? '已启用' : '已关闭' }}{% endraw %}
</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="280">
<template slot-scope="scope">
<el-button
size="mini"
type="primary"
@click="viewGroupPermissions(scope.row)">
查看权限
</el-button>
<el-button
size="mini"
:type="scope.row.robot_status === 'enabled' ? 'danger' : 'success'"
@click="toggleRobotStatus(scope.row)">
{% raw %}{{ scope.row.robot_status === 'enabled' ? '关闭' : '启用' }}{% endraw %}
</el-button>
<el-button
size="mini"
type="info"
@click="viewMessageTrend(scope.row)">
消息趋势
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 批量操作按钮 -->
<div style="margin-top: 20px" v-if="selectedGroups.length > 0">
<el-alert
title="批量操作"
type="info"
:closable="false">
<span>已选择 {% raw %}{{ selectedGroups.length }}{% endraw %} 个群组</span>
</el-alert>
<div style="margin-top: 10px">
<el-button type="success" size="small" @click="batchEnableRobot">批量启用</el-button>
<el-button type="danger" size="small" @click="batchDisableRobot">批量关闭</el-button>
<el-button type="warning" size="small" @click="batchRemoveGroups">批量移除</el-button>
</div>
</div>
</el-card>
</el-col>
</el-row>
<!-- 群组权限管理对话框 -->
<el-dialog
:title="currentGroupName + ' 功能权限管理'"
:visible.sync="permissionDialogVisible"
width="70%">
<el-table :data="permissions" style="width: 100%" border>
<el-table-column prop="feature_id" label="功能ID" width="80"></el-table-column>
<el-table-column prop="feature_description" label="功能描述"></el-table-column>
<el-table-column label="状态" width="100">
<template slot-scope="scope">
<el-tag
:type="scope.row.status === 'enabled' ? 'success' : 'danger'">
{% raw %}{{ scope.row.status === 'enabled' ? '已启用' : '已关闭' }}{% endraw %}
</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="120">
<template slot-scope="scope">
<el-switch
v-model="scope.row.statusBool"
active-color="#13ce66"
inactive-color="#ff4949"
@change="togglePermission(scope.row)">
</el-switch>
</template>
</el-table-column>
</el-table>
<div slot="footer" class="dialog-footer">
<el-button @click="enableAllPermissions" type="success">一键启用全部</el-button>
<el-button @click="disableAllPermissions" type="danger">一键关闭全部</el-button>
<el-button @click="permissionDialogVisible = false">关闭</el-button>
</div>
</el-dialog>
<!-- 添加群组对话框 -->
<el-dialog
title="添加群组"
:visible.sync="addGroupDialogVisible"
width="30%">
<el-form :model="addGroupForm" :rules="addGroupRules" ref="addGroupForm">
<el-form-item label="群组ID" prop="groupId">
<el-input v-model="addGroupForm.groupId" placeholder="请输入群组ID"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="addGroupDialogVisible = false">取消</el-button>
<el-button type="primary" @click="submitAddGroup">确定</el-button>
</span>
</el-dialog>
<!-- 群组消息趋势对话框 -->
<el-dialog
title="群组消息趋势"
:visible.sync="messageTrendDialogVisible"
width="70%">
<div class="chart-container">
<h3>{% raw %}{{ currentGroupName }}{% endraw %} 消息趋势</h3>
<canvas id="messageTrendChart" width="800" height="400"></canvas>
</div>
</el-dialog>
</div>
{% endblock %}
{% block scripts %}
<script>
new Vue({
el: '#app',
mixins: [baseApp],
data() {
return {
groups: [],
permissions: [],
currentGroupId: null,
currentGroupName: '',
searchQuery: '',
selectedGroups: [],
permissionDialogVisible: false,
// 添加群组相关数据
addGroupDialogVisible: false,
addGroupForm: {
groupId: ''
},
addGroupRules: {
groupId: [
{ required: true, message: '请输入群组ID', trigger: 'blur' },
{ pattern: /^\S+$/, message: '群组ID不能包含空格', trigger: 'blur' }
]
},
// 添加消息趋势相关数据
messageTrendDialogVisible: false,
messageTrendData: {
dates: [],
counts: []
}
}
},
computed: {
filteredGroups() {
if (!this.searchQuery) return this.groups;
const query = this.searchQuery.toLowerCase();
return this.groups.filter(group =>
(group.group_id && group.group_id.toLowerCase().includes(query)) ||
(group.group_name && group.group_name.toLowerCase().includes(query))
);
}
},
mounted() {
this.currentView = '6'; // 设置当前菜单项
this.loadGroups();
},
methods: {
loadGroups() {
axios.get('/api/robot/groups')
.then(response => {
if (response.data.success) {
this.groups = response.data.data || [];
} else {
this.$message.error('加载群组失败');
}
})
.catch(error => {
console.error('加载群组失败:', error);
this.$message.error('加载群组失败: ' + error.message);
});
},
handleSelectionChange(selection) {
this.selectedGroups = selection.map(item => item.group_id);
},
viewGroupPermissions(group) {
this.currentGroupId = group.group_id;
this.currentGroupName = group.group_name || group.group_id;
axios.get(`/api/robot/group/${group.group_id}/permissions`)
.then(response => {
if (response.data.success) {
// 添加布尔值属性用于switch组件
const permissionsData = response.data.data || [];
this.permissions = permissionsData.map(p => ({
...p,
statusBool: p.status === 'enabled'
}));
this.permissionDialogVisible = true;
} else {
this.$message.error('加载权限失败');
}
})
.catch(error => {
console.error('加载权限失败:', error);
this.$message.error('加载权限失败: ' + error.message);
});
},
togglePermission(permission) {
const newStatus = permission.statusBool ? 'enabled' : 'disabled';
axios.post(`/api/robot/group/${this.currentGroupId}/permissions`, {
feature_id: permission.feature_id,
status: newStatus
})
.then(response => {
if (response.data.success) {
permission.status = newStatus;
this.$message.success('更新权限成功');
} else {
// 恢复原状态
permission.statusBool = !permission.statusBool;
this.$message.error('更新权限失败');
}
})
.catch(error => {
// 恢复原状态
permission.statusBool = !permission.statusBool;
console.error('更新权限失败:', error);
this.$message.error('更新权限失败: ' + error.message);
});
},
enableAllPermissions() {
this.updateAllPermissions('enabled');
},
disableAllPermissions() {
this.updateAllPermissions('disabled');
},
updateAllPermissions(status) {
axios.post(`/api/robot/group/${this.currentGroupId}/permissions`, {
status: status
})
.then(response => {
if (response.data.success) {
// 更新本地数据
this.permissions.forEach(p => {
p.status = status;
p.statusBool = status === 'enabled';
});
this.$message.success('批量更新权限成功');
} else {
this.$message.error('批量更新权限失败');
}
})
.catch(error => {
console.error('批量更新权限失败:', error);
this.$message.error('批量更新权限失败: ' + error.message);
});
},
toggleRobotStatus(group) {
const newStatus = group.robot_status === 'enabled' ? 'disabled' : 'enabled';
axios.post(`/api/robot/group/${group.group_id}/status`, {
status: newStatus
})
.then(response => {
if (response.data.success) {
group.robot_status = newStatus;
this.$message.success('更新机器人状态成功');
} else {
this.$message.error('更新机器人状态失败');
}
})
.catch(error => {
console.error('更新机器人状态失败:', error);
this.$message.error('更新机器人状态失败: ' + error.message);
});
},
showAddGroupDialog() {
this.addGroupForm.groupId = '';
this.addGroupDialogVisible = true;
},
submitAddGroup() {
this.$refs.addGroupForm.validate(valid => {
if (valid) {
axios.post('/api/robot/group', {
group_id: this.addGroupForm.groupId
})
.then(response => {
if (response.data.success) {
this.addGroupDialogVisible = false;
this.$message.success('添加群组成功');
// 重新加载群组列表
this.loadGroups();
} else {
this.$message.error('添加群组失败');
}
})
.catch(error => {
console.error('添加群组失败:', error);
this.$message.error('添加群组失败: ' + error.message);
});
}
});
},
batchEnableRobot() {
this.batchUpdateRobotStatus('enabled');
},
batchDisableRobot() {
this.batchUpdateRobotStatus('disabled');
},
batchUpdateRobotStatus(status) {
if (this.selectedGroups.length === 0) {
this.$message.warning('请先选择群组');
return;
}
axios.post('/api/robot/batch_operation', {
operation: 'update_status',
group_ids: this.selectedGroups,
status: status
})
.then(response => {
if (response.data.success) {
// 更新本地数据
this.groups.forEach(g => {
if (this.selectedGroups.includes(g.group_id)) {
g.robot_status = status;
}
});
this.$message.success('批量更新状态成功');
} else {
this.$message.error('批量更新状态失败');
}
})
.catch(error => {
console.error('批量更新状态失败:', error);
this.$message.error('批量更新状态失败: ' + error.message);
});
},
batchRemoveGroups() {
if (this.selectedGroups.length === 0) {
this.$message.warning('请先选择群组');
return;
}
this.$confirm(`确定要批量移除 ${this.selectedGroups.length} 个群组吗? 此操作将清除这些群组的所有设置。`, '警告', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'danger'
}).then(() => {
axios.post('/api/robot/batch_operation', {
operation: 'remove_groups',
group_ids: this.selectedGroups
})
.then(response => {
if (response.data.success) {
// 从列表中移除这些群组
this.groups = this.groups.filter(g => !this.selectedGroups.includes(g.group_id));
this.selectedGroups = [];
this.$message.success('批量移除成功');
} else {
this.$message.error('批量移除失败');
}
})
.catch(error => {
console.error('批量移除失败:', error);
this.$message.error('批量移除失败: ' + error.message);
});
}).catch(() => {});
},
// 添加查看消息趋势的方法
viewMessageTrend(group) {
this.currentGroupId = group.group_id;
this.currentGroupName = group.group_name || group.group_id;
// 获取消息趋势数据
const days = parseInt(this.timeRange || 7);
axios.get(`/api/robot/group/${group.group_id}/message_trend?days=${days}`)
.then(response => {
if (response.data.success) {
this.messageTrendData = response.data.data || { dates: [], counts: [] };
this.messageTrendDialogVisible = true;
// 在下一个DOM更新周期渲染图表
this.$nextTick(() => {
this.renderMessageTrendChart();
});
} else {
this.$message.error('加载消息趋势失败');
}
})
.catch(error => {
console.error('加载消息趋势失败:', error);
this.$message.error('加载消息趋势失败: ' + error.message);
});
},
// 渲染消息趋势图表
renderMessageTrendChart() {
const ctx = document.getElementById('messageTrendChart').getContext('2d');
// 销毁旧图表
if (this.charts && this.charts.messageTrendChart) {
this.charts.messageTrendChart.destroy();
}
// 确保charts对象存在
if (!this.charts) {
this.charts = {};
}
// 创建新图表
this.charts.messageTrendChart = new Chart(ctx, {
type: 'line',
data: {
labels: this.messageTrendData.dates,
datasets: [
{
label: '消息数量',
data: this.messageTrendData.counts,
fill: false,
backgroundColor: 'rgba(75, 192, 192, 0.6)',
borderColor: 'rgba(75, 192, 192, 1)',
tension: 0.1
}
]
},
options: {
responsive: true,
scales: {
y: {
beginAtZero: true
}
}
}
});
}
}
});
</script>
{% endblock %}