first commit
This commit is contained in:
551
src/pages/admin/statistics/AdminStatisticsPage.vue
Normal file
551
src/pages/admin/statistics/AdminStatisticsPage.vue
Normal file
@@ -0,0 +1,551 @@
|
||||
<template>
|
||||
<div class="admin-statistics-page">
|
||||
<div class="page-header">
|
||||
<h1>统计管理</h1>
|
||||
<p>管理员专用统计管理界面</p>
|
||||
</div>
|
||||
|
||||
<!-- 仪表板管理 -->
|
||||
<el-card class="dashboard-card" shadow="hover">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>仪表板管理</span>
|
||||
<el-button type="primary" @click="showCreateDialog = true">
|
||||
<el-icon><Plus /></el-icon>
|
||||
创建仪表板
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 筛选条件 -->
|
||||
<div class="filter-section">
|
||||
<el-form :inline="true" :model="filterForm" class="filter-form">
|
||||
<el-form-item label="用户角色">
|
||||
<el-select v-model="filterForm.user_role" placeholder="选择角色" clearable>
|
||||
<el-option label="全部" value="" />
|
||||
<el-option label="管理员" value="admin" />
|
||||
<el-option label="普通用户" value="user" />
|
||||
<el-option label="经理" value="manager" />
|
||||
<el-option label="分析师" value="analyst" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="访问级别">
|
||||
<el-select v-model="filterForm.access_level" placeholder="选择级别" clearable>
|
||||
<el-option label="全部" value="" />
|
||||
<el-option label="私有" value="private" />
|
||||
<el-option label="公开" value="public" />
|
||||
<el-option label="共享" value="shared" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态">
|
||||
<el-select v-model="filterForm.is_active" placeholder="选择状态" clearable>
|
||||
<el-option label="全部" value="" />
|
||||
<el-option label="激活" :value="true" />
|
||||
<el-option label="停用" :value="false" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="默认">
|
||||
<el-select v-model="filterForm.is_default" placeholder="是否默认" clearable>
|
||||
<el-option label="全部" value="" />
|
||||
<el-option label="是" :value="true" />
|
||||
<el-option label="否" :value="false" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="loadDashboards">
|
||||
<el-icon><SearchIcon /></el-icon>
|
||||
搜索
|
||||
</el-button>
|
||||
<el-button @click="resetFilter">
|
||||
<el-icon><Refresh /></el-icon>
|
||||
重置
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<!-- 仪表板列表 -->
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="dashboards"
|
||||
stripe
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-table-column prop="name" label="仪表板名称" min-width="150" />
|
||||
<el-table-column prop="description" label="描述" min-width="200" show-overflow-tooltip />
|
||||
<el-table-column prop="user_role" label="用户角色" width="100">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="getRoleTagType(row.user_role)">
|
||||
{{ getRoleName(row.user_role) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="access_level" label="访问级别" width="100">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="getAccessLevelTagType(row.access_level)">
|
||||
{{ getAccessLevelName(row.access_level) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="is_default" label="默认" width="80">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.is_default ? 'success' : 'info'">
|
||||
{{ row.is_default ? '是' : '否' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="is_active" label="状态" width="80">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.is_active ? 'success' : 'danger'">
|
||||
{{ row.is_active ? '激活' : '停用' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="refresh_interval" label="刷新间隔(秒)" width="120" />
|
||||
<el-table-column prop="created_at" label="创建时间" width="180">
|
||||
<template #default="{ row }">
|
||||
{{ formatDate(row.created_at) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="200" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button size="small" @click="viewDashboard(row)">
|
||||
<el-icon><ViewIcon /></el-icon>
|
||||
查看
|
||||
</el-button>
|
||||
<el-button size="small" type="primary" @click="editDashboard(row)">
|
||||
<el-icon><Edit /></el-icon>
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button size="small" type="danger" @click="deleteDashboard(row)">
|
||||
<el-icon><Delete /></el-icon>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 分页 -->
|
||||
<div class="pagination-container">
|
||||
<el-pagination
|
||||
v-model:current-page="pagination.page"
|
||||
v-model:page-size="pagination.pageSize"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
:total="pagination.total"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!-- 创建/编辑仪表板对话框 -->
|
||||
<el-dialog
|
||||
v-model="showCreateDialog"
|
||||
:title="editingDashboard ? '编辑仪表板' : '创建仪表板'"
|
||||
width="600px"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<el-form
|
||||
ref="dashboardFormRef"
|
||||
:model="dashboardForm"
|
||||
:rules="dashboardRules"
|
||||
label-width="100px"
|
||||
>
|
||||
<el-form-item label="仪表板名称" prop="name">
|
||||
<el-input v-model="dashboardForm.name" placeholder="请输入仪表板名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="描述" prop="description">
|
||||
<el-input
|
||||
v-model="dashboardForm.description"
|
||||
type="textarea"
|
||||
:rows="3"
|
||||
placeholder="请输入仪表板描述"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="用户角色" prop="user_role">
|
||||
<el-select v-model="dashboardForm.user_role" placeholder="选择用户角色">
|
||||
<el-option label="管理员" value="admin" />
|
||||
<el-option label="普通用户" value="user" />
|
||||
<el-option label="经理" value="manager" />
|
||||
<el-option label="分析师" value="analyst" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="访问级别" prop="access_level">
|
||||
<el-select v-model="dashboardForm.access_level" placeholder="选择访问级别">
|
||||
<el-option label="私有" value="private" />
|
||||
<el-option label="公开" value="public" />
|
||||
<el-option label="共享" value="shared" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="刷新间隔" prop="refresh_interval">
|
||||
<el-input-number
|
||||
v-model="dashboardForm.refresh_interval"
|
||||
:min="30"
|
||||
:max="3600"
|
||||
:step="30"
|
||||
placeholder="刷新间隔(秒)"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="是否默认">
|
||||
<el-switch v-model="dashboardForm.is_default" />
|
||||
</el-form-item>
|
||||
<el-form-item label="是否激活">
|
||||
<el-switch v-model="dashboardForm.is_active" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="showCreateDialog = false">取消</el-button>
|
||||
<el-button type="primary" :loading="creating" @click="saveDashboard">
|
||||
{{ editingDashboard ? '更新' : '创建' }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
adminCreateDashboard,
|
||||
adminDeleteDashboard,
|
||||
adminGetDashboards,
|
||||
adminUpdateDashboard
|
||||
} from '@/api/statistics'
|
||||
import {
|
||||
Delete,
|
||||
Edit,
|
||||
Plus,
|
||||
Refresh,
|
||||
Search as SearchIcon,
|
||||
View as ViewIcon
|
||||
} from '@element-plus/icons-vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { onMounted, reactive, ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
export default {
|
||||
name: 'AdminStatisticsPage',
|
||||
components: {
|
||||
Plus,
|
||||
SearchIcon,
|
||||
Refresh,
|
||||
ViewIcon,
|
||||
Edit,
|
||||
Delete
|
||||
},
|
||||
setup() {
|
||||
const router = useRouter()
|
||||
const loading = ref(false)
|
||||
const dashboards = ref([])
|
||||
const showCreateDialog = ref(false)
|
||||
const creating = ref(false)
|
||||
const editingDashboard = ref(null)
|
||||
const dashboardFormRef = ref()
|
||||
|
||||
// 筛选表单
|
||||
const filterForm = reactive({
|
||||
user_role: '',
|
||||
access_level: '',
|
||||
is_active: '',
|
||||
is_default: ''
|
||||
})
|
||||
|
||||
// 分页
|
||||
const pagination = reactive({
|
||||
page: 1,
|
||||
pageSize: 20,
|
||||
total: 0
|
||||
})
|
||||
|
||||
// 仪表板表单
|
||||
const dashboardForm = reactive({
|
||||
name: '',
|
||||
description: '',
|
||||
user_role: 'user',
|
||||
access_level: 'private',
|
||||
refresh_interval: 300,
|
||||
is_default: false,
|
||||
is_active: true
|
||||
})
|
||||
|
||||
// 表单验证规则
|
||||
const dashboardRules = {
|
||||
name: [{ required: true, message: '请输入仪表板名称', trigger: 'blur' }],
|
||||
description: [{ required: true, message: '请输入仪表板描述', trigger: 'blur' }],
|
||||
user_role: [{ required: true, message: '请选择用户角色', trigger: 'change' }],
|
||||
access_level: [{ required: true, message: '请选择访问级别', trigger: 'change' }],
|
||||
refresh_interval: [{ required: true, message: '请输入刷新间隔', trigger: 'blur' }]
|
||||
}
|
||||
|
||||
// 加载仪表板列表
|
||||
const loadDashboards = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const params = {
|
||||
page: pagination.page,
|
||||
page_size: pagination.pageSize,
|
||||
...filterForm
|
||||
}
|
||||
|
||||
// 移除空值参数
|
||||
Object.keys(params).forEach(key => {
|
||||
if (params[key] === '' || params[key] === null || params[key] === undefined) {
|
||||
delete params[key]
|
||||
}
|
||||
})
|
||||
|
||||
const response = await adminGetDashboards(params)
|
||||
|
||||
if (response.success) {
|
||||
dashboards.value = response.data.items || []
|
||||
pagination.total = response.data.total || 0
|
||||
} else {
|
||||
ElMessage.error(response.message || '获取仪表板列表失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取仪表板列表失败:', error)
|
||||
ElMessage.error('获取仪表板列表失败')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 重置筛选条件
|
||||
const resetFilter = () => {
|
||||
Object.keys(filterForm).forEach(key => {
|
||||
filterForm[key] = ''
|
||||
})
|
||||
pagination.page = 1
|
||||
loadDashboards()
|
||||
}
|
||||
|
||||
// 查看仪表板
|
||||
const viewDashboard = (dashboard) => {
|
||||
// 跳转到仪表板详情页面
|
||||
router.push(`/statistics/dashboard/${dashboard.id}`)
|
||||
}
|
||||
|
||||
// 编辑仪表板
|
||||
const editDashboard = (dashboard) => {
|
||||
editingDashboard.value = dashboard
|
||||
Object.assign(dashboardForm, {
|
||||
name: dashboard.name,
|
||||
description: dashboard.description,
|
||||
user_role: dashboard.user_role,
|
||||
access_level: dashboard.access_level,
|
||||
refresh_interval: dashboard.refresh_interval,
|
||||
is_default: dashboard.is_default,
|
||||
is_active: dashboard.is_active
|
||||
})
|
||||
showCreateDialog.value = true
|
||||
}
|
||||
|
||||
// 删除仪表板
|
||||
const deleteDashboard = async (dashboard) => {
|
||||
try {
|
||||
await ElMessageBox.confirm(
|
||||
`确定要删除仪表板"${dashboard.name}"吗?`,
|
||||
'确认删除',
|
||||
{
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}
|
||||
)
|
||||
|
||||
const response = await adminDeleteDashboard(dashboard.id)
|
||||
if (response.success) {
|
||||
ElMessage.success('删除成功')
|
||||
loadDashboards()
|
||||
} else {
|
||||
ElMessage.error(response.message || '删除失败')
|
||||
}
|
||||
} catch (error) {
|
||||
if (error !== 'cancel') {
|
||||
console.error('删除仪表板失败:', error)
|
||||
ElMessage.error('删除失败')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 保存仪表板
|
||||
const saveDashboard = async () => {
|
||||
try {
|
||||
await dashboardFormRef.value.validate()
|
||||
creating.value = true
|
||||
|
||||
const data = { ...dashboardForm }
|
||||
let response
|
||||
|
||||
if (editingDashboard.value) {
|
||||
response = await adminUpdateDashboard(editingDashboard.value.id, data)
|
||||
} else {
|
||||
response = await adminCreateDashboard(data)
|
||||
}
|
||||
|
||||
if (response.success) {
|
||||
ElMessage.success(editingDashboard.value ? '更新成功' : '创建成功')
|
||||
showCreateDialog.value = false
|
||||
resetForm()
|
||||
loadDashboards()
|
||||
} else {
|
||||
ElMessage.error(response.message || '操作失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('保存仪表板失败:', error)
|
||||
ElMessage.error('操作失败')
|
||||
} finally {
|
||||
creating.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 重置表单
|
||||
const resetForm = () => {
|
||||
editingDashboard.value = null
|
||||
Object.assign(dashboardForm, {
|
||||
name: '',
|
||||
description: '',
|
||||
user_role: 'user',
|
||||
access_level: 'private',
|
||||
refresh_interval: 300,
|
||||
is_default: false,
|
||||
is_active: true
|
||||
})
|
||||
dashboardFormRef.value?.resetFields()
|
||||
}
|
||||
|
||||
// 分页处理
|
||||
const handleSizeChange = (val) => {
|
||||
pagination.pageSize = val
|
||||
pagination.page = 1
|
||||
loadDashboards()
|
||||
}
|
||||
|
||||
const handleCurrentChange = (val) => {
|
||||
pagination.page = val
|
||||
loadDashboards()
|
||||
}
|
||||
|
||||
// 工具函数
|
||||
const getRoleName = (role) => {
|
||||
const roleNames = {
|
||||
admin: '管理员',
|
||||
user: '普通用户',
|
||||
manager: '经理',
|
||||
analyst: '分析师'
|
||||
}
|
||||
return roleNames[role] || role
|
||||
}
|
||||
|
||||
const getRoleTagType = (role) => {
|
||||
const tagTypes = {
|
||||
admin: 'danger',
|
||||
user: 'primary',
|
||||
manager: 'warning',
|
||||
analyst: 'success'
|
||||
}
|
||||
return tagTypes[role] || 'info'
|
||||
}
|
||||
|
||||
const getAccessLevelName = (level) => {
|
||||
const levelNames = {
|
||||
private: '私有',
|
||||
public: '公开',
|
||||
shared: '共享'
|
||||
}
|
||||
return levelNames[level] || level
|
||||
}
|
||||
|
||||
const getAccessLevelTagType = (level) => {
|
||||
const tagTypes = {
|
||||
private: 'info',
|
||||
public: 'success',
|
||||
shared: 'warning'
|
||||
}
|
||||
return tagTypes[level] || 'info'
|
||||
}
|
||||
|
||||
const formatDate = (date) => {
|
||||
if (!date) return '-'
|
||||
return new Date(date).toLocaleString('zh-CN')
|
||||
}
|
||||
|
||||
// 生命周期
|
||||
onMounted(() => {
|
||||
loadDashboards()
|
||||
})
|
||||
|
||||
return {
|
||||
loading,
|
||||
dashboards,
|
||||
showCreateDialog,
|
||||
creating,
|
||||
editingDashboard,
|
||||
dashboardFormRef,
|
||||
filterForm,
|
||||
pagination,
|
||||
dashboardForm,
|
||||
dashboardRules,
|
||||
loadDashboards,
|
||||
resetFilter,
|
||||
viewDashboard,
|
||||
editDashboard,
|
||||
deleteDashboard,
|
||||
saveDashboard,
|
||||
handleSizeChange,
|
||||
handleCurrentChange,
|
||||
getRoleName,
|
||||
getRoleTagType,
|
||||
getAccessLevelName,
|
||||
getAccessLevelTagType,
|
||||
formatDate
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.admin-statistics-page {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.page-header {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.page-header h1 {
|
||||
margin: 0 0 8px 0;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.page-header p {
|
||||
margin: 0;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.dashboard-card {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.filter-section {
|
||||
margin-bottom: 20px;
|
||||
padding: 16px;
|
||||
background-color: #f5f7fa;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.filter-form {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.pagination-container {
|
||||
margin-top: 20px;
|
||||
text-align: right;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user