feat: add system quality improvement plan and implementation
This commit is contained in:
@@ -1,56 +1,78 @@
|
||||
<template>
|
||||
<div class="dashboard">
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="6">
|
||||
<a-card>
|
||||
<a-statistic title="用户总数" :value="stats.userCount" :prefix="h(UserOutlined)" />
|
||||
</a-card>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<a-card>
|
||||
<a-statistic title="角色总数" :value="stats.roleCount" :prefix="h(TeamOutlined)" />
|
||||
</a-card>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<a-card>
|
||||
<a-statistic title="今日登录" :value="stats.todayLogin" :prefix="h(LogoutOutlined)" />
|
||||
</a-card>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<a-card>
|
||||
<a-statistic title="操作日志" :value="stats.operationLog" :prefix="h(FileTextOutlined)" />
|
||||
</a-card>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-row :gutter="16" style="margin-top: 16px">
|
||||
<a-col :span="12">
|
||||
<a-card title="最近登录">
|
||||
<a-timeline>
|
||||
<a-timeline-item v-for="item in recentLogins" :key="item.id" :color="item.status === '0' ? 'green' : 'red'">
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="6">
|
||||
<el-card v-loading="loading">
|
||||
<el-statistic title="用户总数" :value="stats.userCount">
|
||||
<template #prefix>
|
||||
<el-icon><User /></el-icon>
|
||||
</template>
|
||||
</el-statistic>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-card v-loading="loading">
|
||||
<el-statistic title="角色总数" :value="stats.roleCount">
|
||||
<template #prefix>
|
||||
<el-icon><UserFilled /></el-icon>
|
||||
</template>
|
||||
</el-statistic>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-card v-loading="loading">
|
||||
<el-statistic title="今日登录" :value="stats.todayLogin">
|
||||
<template #prefix>
|
||||
<el-icon><ArrowRight /></el-icon>
|
||||
</template>
|
||||
</el-statistic>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-card v-loading="loading">
|
||||
<el-statistic title="操作日志" :value="stats.operationLog">
|
||||
<template #prefix>
|
||||
<el-icon><Document /></el-icon>
|
||||
</template>
|
||||
</el-statistic>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16" style="margin-top: 16px">
|
||||
<el-col :span="12">
|
||||
<el-card title="最近登录" v-loading="loading">
|
||||
<el-timeline>
|
||||
<el-timeline-item
|
||||
v-for="item in recentLogins"
|
||||
:key="item.id"
|
||||
:type="item.status === '0' ? 'success' : 'danger'"
|
||||
>
|
||||
<p>{{ item.username }} - {{ item.ip }}</p>
|
||||
<p>{{ item.loginTime }}</p>
|
||||
</a-timeline-item>
|
||||
</a-timeline>
|
||||
</a-card>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-card title="系统信息">
|
||||
<a-descriptions :column="1" bordered size="small">
|
||||
<a-descriptions-item label="系统版本">1.0.0</a-descriptions-item>
|
||||
<a-descriptions-item label="Java版本">21</a-descriptions-item>
|
||||
<a-descriptions-item label="前端框架">Vue 3 + Ant Design Vue</a-descriptions-item>
|
||||
<a-descriptions-item label="数据库">PostgreSQL</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
</a-card>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</el-timeline-item>
|
||||
</el-timeline>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-card title="系统信息" v-loading="loading">
|
||||
<el-descriptions :column="1" border>
|
||||
<el-descriptions-item label="系统版本">{{ systemInfo.version }}</el-descriptions-item>
|
||||
<el-descriptions-item label="Java版本">{{ systemInfo.javaVersion }}</el-descriptions-item>
|
||||
<el-descriptions-item label="前端框架">{{ systemInfo.frontendFramework }}</el-descriptions-item>
|
||||
<el-descriptions-item label="数据库">{{ systemInfo.database }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, h } from 'vue'
|
||||
import { UserOutlined, TeamOutlined, LogoutOutlined, FileTextOutlined } from '@ant-design/icons-vue'
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import { User, UserFilled, ArrowRight, Document } from '@element-plus/icons-vue'
|
||||
import request from '@/utils/request'
|
||||
|
||||
const loading = ref(false)
|
||||
const stats = reactive({
|
||||
userCount: 0,
|
||||
roleCount: 0,
|
||||
@@ -59,6 +81,50 @@ const stats = reactive({
|
||||
})
|
||||
|
||||
const recentLogins = ref<any[]>([])
|
||||
const systemInfo = reactive({
|
||||
version: '1.0.0',
|
||||
javaVersion: '21',
|
||||
frontendFramework: 'Vue 3 + Element Plus',
|
||||
database: 'PostgreSQL'
|
||||
})
|
||||
|
||||
const fetchStats = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const userCountRes: any = await request.get('/users/count')
|
||||
stats.userCount = userCountRes || 0
|
||||
|
||||
const roleCountRes: any = await request.get('/roles/count')
|
||||
stats.roleCount = roleCountRes || 0
|
||||
|
||||
const todayLoginRes: any = await request.get('/logs/login/today/count')
|
||||
stats.todayLogin = todayLoginRes || 0
|
||||
|
||||
const operationLogRes: any = await request.get('/logs/operation/count')
|
||||
stats.operationLog = operationLogRes || 0
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch stats:', error)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const fetchRecentLogins = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const res: any = await request.get('/logs/login/recent?limit=10')
|
||||
recentLogins.value = res || []
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch recent logins:', error)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
fetchStats()
|
||||
fetchRecentLogins()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
Reference in New Issue
Block a user