perf: 拆分控制台仪表盘、审计台仪表盘

This commit is contained in:
“huailei000”
2022-12-01 10:52:43 +08:00
committed by huailei
parent 179c420e9d
commit 66a33d0c44
16 changed files with 61 additions and 733 deletions

View File

@@ -23,7 +23,7 @@ export default {
children: [
{
path: '/audit/dashboard',
component: () => import('@/views/dashboard/index'),
component: () => import('@/views/dashboard/Audit/index'),
name: 'AuditDashboard',
meta: {
icon: 'dashboard',

View File

@@ -27,7 +27,7 @@ export default {
children: [
{
path: '/console/dashboard',
component: () => import('@/views/dashboard/index'),
component: () => import('@/views/dashboard/Console/index'),
name: 'AdminDashboard',
meta: {
icon: 'dashboard',

View File

@@ -5,7 +5,7 @@
</template>
<script>
import ColumnChart from './components/ColumnChart'
import ColumnChart from '../components/ColumnChart'
export default {
components: {
ColumnChart

View File

@@ -0,0 +1,51 @@
<template>
<Page>
<div v-if="this.$hasPerm('rbac.view_audit')">
<Announcement />
<el-row :gutter="16">
<el-col :lg="12" :sm="24">
审计台仪表盘
</el-col>
<el-col :lg="12" :sm="24">
审计台仪表盘
</el-col>
</el-row>
<TrendSummary />
</div>
<Page403 v-else />
</Page>
</template>
<script>
import { Announcement } from '@/components'
import { Page } from '@/layout/components'
import TrendSummary from './TrendSummary'
import Page403 from '@/views/403'
export default {
components: {
Page,
Announcement,
TrendSummary,
Page403
},
props: {
},
data() {
return {
}
},
created() {
},
methods: {
}
}
</script>
<style scoped>
</style>

View File

@@ -8,8 +8,8 @@
</template>
<script>
import Title from './components/Title.vue'
import ProgressChart from './components/ProgressChart.vue'
import Title from '../components/Title.vue'
import ProgressChart from '../components/ProgressChart.vue'
export default {
components: {
Title,

View File

@@ -12,13 +12,10 @@
</template>
<script>
import DataCard from './components/DataCard.vue'
import DataCard from '../components/DataCard.vue'
export default {
components: {
DataCard
},
props: {
},
data() {
const documentStyle = document.documentElement.style

View File

@@ -12,7 +12,7 @@
</template>
<script>
import RankTable from './components/RankTable.vue'
import RankTable from '../components/RankTable.vue'
export default {
components: {
RankTable

View File

@@ -1,6 +1,6 @@
<template>
<Page>
<div v-if="this.$hasPerm('rbac.view_console|rbac.view_audit')">
<div v-if="this.$hasPerm('rbac.view_console')">
<Announcement />
<el-row :gutter="16">
<el-col :lg="12" :sm="24">
@@ -22,11 +22,11 @@
import { Announcement } from '@/components'
import { Page } from '@/layout/components'
import Page403 from '@/views/403'
import RealTimeSummary from '../components/RealTimeSummary.vue'
import LineChart from '../components/LineChart.vue'
import DataSummary from './DataSummary'
import AssetProportionSummary from './AssetProportionSummary'
import RankSummary from './RankSummary'
import RealTimeSummary from './components/RealTimeSummary.vue'
import LineChart from './components/LineChart.vue'
export default {
name: 'Dashboard',

View File

@@ -1,203 +0,0 @@
<template>
<div class="statistic-box">
<h4>{{ $t('dashboard.ActiveUserAssetsRatioTitle') }}</h4>
<el-row :gutter="2">
<el-col :md="12" :sm="10">
<echarts :options="userOption" :autoresize="true" />
<div style="" class="print-display">
<div class="circle-icon active-user" />
<label>{{ $t('dashboard.ActiveUser') }}</label>
<div class="circle-icon disabled-user" />
<label>{{ $t('dashboard.DisabledUser') }}</label>
<div class="circle-icon inactive-user" />
<label>{{ $t('dashboard.InActiveUser') }}</label>
</div>
</el-col>
<el-col :md="12" :sm="10">
<echarts :options="AssetOption" :autoresize="true" />
<div style="" class="print-display">
<div class="circle-icon active-asset" />
<label>{{ $t('dashboard.ActiveAsset') }}</label>
<div class="circle-icon disabled-asset" />
<label>{{ $t('dashboard.DisabledAsset') }}</label>
<div class="circle-icon inactive-asset" />
<label>{{ $t('dashboard.InActiveAsset') }}</label>
</div>
</el-col>
</el-row>
</div>
</template>
<script>
import 'echarts/lib/chart/pie'
import 'echarts/lib/component/tooltip'
import 'echarts/lib/component/title'
export default {
name: 'LoginActivePin',
props: {
range: {
type: String,
default: 'weekly'
}
},
data() {
return {
userConnectData: {
dates_total_count_active_users: 0,
dates_total_count_disabled_users: 0,
dates_total_count_inactive_users: 0
},
assetConnectData: {
dates_total_count_active_assets: 0,
dates_total_count_disabled_assets: 0,
dates_total_count_inactive_assets: 0
}
}
},
computed: {
themeColor() {
const documentStyle = document.documentElement.style
return {
primary: documentStyle.getPropertyValue('--color-primary'),
info: documentStyle.getPropertyValue('--color-info'),
success: documentStyle.getPropertyValue('--color-success')
}
},
userOption() {
const { primary, info, success } = this.themeColor
return {
legend: {
show: false
},
title: {
subtext: this.$t('dashboard.User')
},
color: [primary, info, success],
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b}: {c} ({d}%)'
},
series: [
{
name: this.$t('dashboard.UserRatio'),
type: 'pie',
radius: ['50%', '70%'],
avoidLabelOverlap: false,
label: {
show: false,
position: 'center'
},
emphasis: {
label: {
show: true,
fontSize: '18',
fontWeight: 'bold'
}
},
labelLine: {
show: false
},
data: [
{ name: this.$t('dashboard.ActiveUser'), value: this.userConnectData.dates_total_count_active_users },
{ name: this.$t('dashboard.DisabledUser'), value: this.userConnectData.dates_total_count_disabled_users },
{ name: this.$t('dashboard.InActiveUser'), value: this.userConnectData.dates_total_count_inactive_users }
]
}
]
}
},
AssetOption() {
const { primary, info, success } = this.themeColor
return {
legend: {
show: false
},
title: {
subtext: this.$t('dashboard.Asset')
},
color: [primary, info, success],
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b}: {c} ({d}%)'
},
series: [
{
name: this.$t('dashboard.AssetRatio'),
type: 'pie',
radius: ['50%', '70%'],
avoidLabelOverlap: false,
label: {
show: false,
position: 'center'
},
emphasis: {
label: {
show: true,
fontSize: '18',
fontWeight: 'bold'
}
},
labelLine: {
show: false
},
data: [
{ name: this.$t('dashboard.ActiveAsset'), value: this.assetConnectData.dates_total_count_active_assets },
{ name: this.$t('dashboard.DisabledAsset'), value: this.assetConnectData.dates_total_count_disabled_assets },
{ name: this.$t('dashboard.InActiveAsset'), value: this.assetConnectData.dates_total_count_inactive_assets }
]
}
]
}
}
},
watch: {
range() {
this.getTotalActiveRadioData()
}
},
mounted() {
this.getTotalActiveRadioData()
},
methods: {
async getTotalActiveRadioData() {
let url = '/api/v1/index/?dates_total_count_users=1&dates_total_count_assets=1'
if (this.range === 'monthly') {
url = `${url}&monthly=1`
}
const data = await this.$axios.get(url)
this.userConnectData = data
this.assetConnectData = data
}
}
}
</script>
<style lang="scss" scoped>
@import "~@/styles/variables.scss";
.echarts {
width: 100%;
height: 250px;
}
.print-display {
display: none;
}
.circle-icon {
width: 14px;
height: 14px;
-moz-border-radius: 7px;
-webkit-border-radius: 7px;
border-radius: 7px;
display:inline-block;
background: $--color-primary;
}
@media print {
.el-col-24{
width: 50% !important;
}
.print-display {
display: inherit;
}
}
</style>

View File

@@ -1,148 +0,0 @@
<template>
<div>
<echarts ref="echarts" :options="options" :autoresize="true" theme="light" class="disabled-when-print" @finished="getDataUrl" />
<img v-if="dataUrl" :src="dataUrl" class="enabled-when-print" style="display: none;width: 100%;">
</div>
</template>
<script>
import 'echarts/lib/chart/line'
import 'echarts/lib/component/legend'
export default {
name: 'LoginMetric',
props: {
range: {
type: String,
default: 'weekly'
}
},
data: function() {
return {
dataUrl: '',
metricsData: {
dates_metrics_date: [],
dates_metrics_total_count_active_assets: [],
dates_metrics_total_count_active_users: [],
dates_metrics_total_count_login: []
}
}
},
computed: {
themeColor() {
const documentStyle = document.documentElement.style
return {
primary: documentStyle.getPropertyValue('--color-primary'),
info: documentStyle.getPropertyValue('--color-info'),
success: documentStyle.getPropertyValue('--color-success')
}
},
options() {
const { primary, info, success } = this.themeColor
return {
title: {
show: false
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
label: {
backgroundColor: '#6a7985'
}
}
},
legend: {
data: [
this.$t('dashboard.LoginCount'),
this.$t('dashboard.LoginUsers'),
this.$t('dashboard.LoginAssets')
]
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
color: [primary, info, success],
xAxis: [
{
type: 'category',
boundaryGap: false,
data: this.metricsData.dates_metrics_date
}
],
yAxis: [
{
type: 'value'
}
],
animationDuration: 500,
series: [
{
name: this.$t('dashboard.LoginCount'),
type: 'line',
areaStyle: {},
smooth: true,
data: this.metricsData.dates_metrics_total_count_login
},
{
name: this.$t('dashboard.LoginUsers'),
type: 'line',
areaStyle: {},
smooth: true,
data: this.metricsData.dates_metrics_total_count_active_users
},
{
name: this.$t('dashboard.LoginAssets'),
type: 'line',
areaStyle: {},
smooth: true,
data: this.metricsData.dates_metrics_total_count_active_assets
}
]
}
}
},
watch: {
range() {
this.getMetricData()
}
},
mounted() {
this.getMetricData()
},
methods: {
async getMetricData() {
let url = '/api/v1/index/?dates_metrics=1&'
if (this.range === 'monthly') {
url = `${url}&monthly=1`
}
this.metricsData = await this.$axios.get(url)
},
getDataUrl() {
this.dataUrl = this.$refs.echarts.getDataURL({
})
}
}
}
</script>
<style scoped>
.echarts {
width: 100%;
height: 300px;
}
@media print {
.disabled-when-print{
display: none;
}
.enabled-when-print{
display: inherit !important;
}
.print-margin{
margin-top: 10px;
}
}
</style>

View File

@@ -1,80 +0,0 @@
<template>
<div class="white-bg dashboard-header print-margin">
<el-row>
<el-col :md="12" :sm="24">
<h2>{{ $t('dashboard.LoginOverview') }}</h2>
</el-col>
<el-col :md="12" :sm="24" class="clearfix">
<el-button-group style="float: right; padding: 0" class="clearfix">
<el-button type="default" size="mini" :class="{ 'active': active === 'weekly'}" @click="changeDates('weekly')">{{ $t('dashboard.Weekly') }}</el-button>
<el-button type="default" size="mini" :class="{ 'active': active === 'monthly'}" @click="changeDates('monthly')">{{ $t('dashboard.Monthly') }}</el-button>
</el-button-group>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :lg="18" :sm="24">
<LoginMetric :range="active" class="card-item" heigth="300px" />
</el-col>
<el-col :lg="6" :sm="24">
<LoginActivePin :range="active" class="card-item" />
</el-col>
</el-row>
</div>
</template>
<script>
import LoginMetric from './LoginMetric'
import LoginActivePin from './LoginActivePin'
export default {
name: 'DatesLoginSummary',
components: { LoginMetric, LoginActivePin },
data() {
return {
active: 'weekly'
}
},
methods: {
changeDates(type) {
this.active = type
}
}
}
</script>
<style scoped>
.dashboard-header {
border-top: 0;
padding: 20px 20px 20px 20px;
}
h2 {
margin-top: 10px;
font-size: 26px;
font-weight: 100;
line-height: 1.1;
color: inherit;
}
.el-button--mini, .el-button--mini.is-round {
padding: 5px 10px;
}
.active {
background-image: none;
border: 1px solid #d2d2d2;
-webkit-box-shadow: inset 0 3px 5px rgba(0,0,0,.125);
}
@media print {
.disabled-when-print{
display: none;
}
.enabled-when-print{
display: inherit !important;
}
.print-margin{
margin-top: 20px;
}
}
</style>

View File

@@ -1,92 +0,0 @@
<template>
<el-row :gutter="10">
<el-col v-for="item of summaryItems" :key="item.title" :md="6" :sm="12" :xs="12">
<SummaryCard :title="item.title" :body="item.body" />
</el-col>
</el-row>
</template>
<script>
import SummaryCard from '@/components/SummaryCard'
export default {
name: 'ResourceSummary',
components: { SummaryCard },
data() {
return {
counter: {
total_count_assets: '.',
total_count_users: '.',
total_count_online_users: '.',
total_count_online_sessions: '.'
}
}
},
computed: {
summaryItems() {
return [
{
title: this.$t('dashboard.UsersTotal'),
body: {
route: { name: 'UserList' },
count: this.counter.total_count_users,
comment: this.$t('dashboard.UsersTotal'),
disabled: !this.$hasPerm('users.view_user')
}
},
{
title: this.$t('dashboard.AssetsTotal'),
body: {
route: { name: 'AssetList' },
count: this.counter.total_count_assets,
comment: this.$t('dashboard.AssetsTotal'),
disabled: !this.$hasPerm('assets.view_asset')
}
},
{
title: this.$t('dashboard.ConnectUsers'),
body: {
route: { name: `SessionList`, params: { activeMenu: 'OnlineList' }},
count: this.counter.total_count_online_users,
comment: this.$t('dashboard.OnlineUsers'),
disabled: !this.$hasPerm('terminal.view_session')
}
},
{
title: this.$t('dashboard.OnlineSessions'),
body: {
route: { name: `SessionList`, params: { activeMenu: 'OnlineList' }},
count: this.counter.total_count_online_sessions,
comment: this.$t('dashboard.OnlineSessions'),
disabled: !this.$hasPerm('terminal.view_session')
}
}
]
}
},
async mounted() {
this.counter = await this.getResourcesCount()
},
methods: {
async getResourcesCount() {
return this.$axios.get('/api/v1/index/?total_count=1')
}
}
}
</script>
<style lang="scss" scoped>
.el-col {
margin-bottom: 25px;
&:last-child {
margin-bottom: 0;
}
}
@media print {
.el-col-24{
width: 50% !important;
}
}
</style>

View File

@@ -1,73 +0,0 @@
<template>
<HeadingIBox :title="title">
<div v-if="dates_login_record_top10_sessions.length > 0" class="feed-activity-list">
<div v-for="(item, index ) of dates_login_record_top10_sessions" :key="item.user + index" class="feed-element">
<a href="#" class="pull-left">
<img alt="image" class="img-circle" :src="avatarUrl">
</a>
<div class="media-body ">
<small class="pull-right">{{ item.timesince }}</small>
<strong>{{ item.user }}</strong>
{{ $t('dashboard.LoginTo') }} {{ item.asset }} <br>
<small class="text-muted">{{ $d(new Date(item.date_start), 'medium') }}</small> <br>
</div>
</div>
</div>
<span v-else>{{ $t('common.NoData') }}</span>
</HeadingIBox>
</template>
<script>
import HeadingIBox from '@/components/IBox/HeadingIBox'
export default {
name: 'Latest10Sessions',
components: { HeadingIBox },
data() {
return {
title: this.$t('dashboard.LatestSessions10'),
avatarUrl: require('@/assets/img/admin.png'),
dates_login_record_top10_sessions: []
}
},
mounted() {
this.getLatest10Sessions()
},
methods: {
async getLatest10Sessions() {
const data = await this.$axios.get('/api/v1/index/?dates_login_record_top10_sessions=1')
this.dates_login_record_top10_sessions = data.dates_login_record_top10_sessions
}
}
}
</script>
<style scoped>
.feed-element, .feed-element .media {
margin-top: 15px;
}
.feed-activity-list .feed-element {
border-bottom: 1px solid #e7eaec;
}
.feed-element {
padding-bottom: 15px;
}
.feed-element > .pull-left {
margin-right: 10px;
}
.feed-element img.img-circle, .dropdown-messages-box img.img-circle {
width: 38px;
height: 38px;
}
.img-circle {
border-radius: 50%;
}
.text-muted {
color: #888888;
padding-top: 5px;
}
</style>

View File

@@ -1,44 +0,0 @@
<template>
<IBox :title="title">
<TopList v-if="assetsItems.length > 0" :items="assetsItems" :unit="unit" class="top-assets" />
<span v-else>{{ $t('common.NoData') }}</span>
</IBox>
</template>
<script>
import IBox from '@/components/IBox'
import TopList from '@/components/TopList'
export default {
name: 'TopAssets',
components: { TopList, IBox },
data() {
return {
title: this.$t('dashboard.TopAssetsOfWeek'),
unit: this.$t('dashboard.TimesWeekUnit'),
dates_login_times_top10_assets: []
}
},
computed: {
assetsItems() {
return this.dates_login_times_top10_assets.map((v) => {
return { name: v.asset, count: v.total }
})
}
},
mounted() {
this.getTopLoginAssets()
},
methods: {
async getTopLoginAssets() {
const data = await this.$axios.get('/api/v1/index/?dates_login_times_top10_assets=1')
this.dates_login_times_top10_assets = data.dates_login_times_top10_assets
}
}
}
</script>
<style scoped>
.top-assets >>> .list-group {
margin-top: 0;
}
</style>

View File

@@ -1,44 +0,0 @@
<template>
<IBox :title="title">
<TopList v-if="userItems.length > 0" :items="userItems" :unit="unit" class="top-users" />
<span v-else>{{ $t('common.NoData') }}</span>
</IBox>
</template>
<script>
import IBox from '@/components/IBox'
import TopList from '@/components/TopList'
export default {
name: 'TopUser',
components: { TopList, IBox },
data() {
return {
title: this.$t('dashboard.TopUsersOfWeek'),
unit: this.$t('dashboard.TimesWeekUnit'),
dates_login_times_top10_users: []
}
},
computed: {
userItems() {
return this.dates_login_times_top10_users.map((v) => {
return { name: v.user, count: v.total }
})
}
},
mounted() {
this.getTopLoginUser()
},
methods: {
async getTopLoginUser() {
const data = await this.$axios.get('/api/v1/index/?dates_login_times_top10_users=1')
this.dates_login_times_top10_users = data.dates_login_times_top10_users
}
}
}
</script>
<style scoped>
.top-users >>> .list-group {
margin-top: 0;
}
</style>

View File

@@ -1,36 +0,0 @@
<template>
<el-row :gutter="10" style="margin-bottom: 20px;margin-top: 20px">
<el-col :md="8" :sm="24">
<TopUser />
</el-col>
<el-col :md="8" :sm="24" class="print-margin-top">
<TopAssets />
</el-col>
<el-col :md="8" :sm="24">
<Latest10Sessions class="card-item print-margin-top" />
</el-col>
</el-row>
</template>
<script>
// import TimelineCard from '@/components/TimelineCard'
import TopAssets from './TopAssets'
import TopUser from './TopUser'
import Latest10Sessions from './Latest10Sessions'
export default {
name: 'TopAndLatestSummary',
components: { TopAssets, TopUser, Latest10Sessions },
data() {
return {}
}
}
</script>
<style scoped>
@media print {
.print-margin-top{
margin-top: 10px;
}
}
</style>