mirror of
https://github.com/jumpserver/lina.git
synced 2025-08-05 16:55:36 +00:00
Perf: Perf Dashboard
This commit is contained in:
parent
369247d987
commit
b1137249f1
@ -41,23 +41,10 @@ export default {
|
|||||||
computed: {
|
computed: {
|
||||||
chartOption() {
|
chartOption() {
|
||||||
return {
|
return {
|
||||||
tooltip: {
|
|
||||||
trigger: 'item',
|
|
||||||
formatter: '{b}: {c} ({d}%)',
|
|
||||||
backgroundColor: 'rgba(255, 255, 255, 0.9)',
|
|
||||||
borderColor: '#eee',
|
|
||||||
borderWidth: 1,
|
|
||||||
padding: [10, 15],
|
|
||||||
textStyle: {
|
|
||||||
color: '#666'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
legend: {
|
legend: {
|
||||||
type: 'scroll',
|
orient: 'vertical',
|
||||||
orient: 'horizontal',
|
top: '13%',
|
||||||
top: 0,
|
right: '15%',
|
||||||
left: 0,
|
|
||||||
right: 0,
|
|
||||||
itemGap: 20,
|
itemGap: 20,
|
||||||
textStyle: {
|
textStyle: {
|
||||||
color: '#666',
|
color: '#666',
|
||||||
@ -65,33 +52,31 @@ export default {
|
|||||||
},
|
},
|
||||||
icon: 'circle',
|
icon: 'circle',
|
||||||
itemWidth: 8,
|
itemWidth: 8,
|
||||||
itemHeight: 8
|
itemHeight: 8,
|
||||||
|
formatter: (name) => {
|
||||||
|
const data = [
|
||||||
|
{ name: '账号收集任务', value: this.counter.total_count_gathered_account_automation },
|
||||||
|
{ name: '账号推送任务', value: this.counter.total_count_push_account_automation },
|
||||||
|
{ name: '账号备份任务', value: this.counter.total_count_backup_account_automation },
|
||||||
|
{ name: '风险账号', value: this.counter.total_count_risk_account },
|
||||||
|
{ name: '集成应用', value: this.counter.total_count_integration_application }
|
||||||
|
]
|
||||||
|
const item = data.find(item => item.name === name)
|
||||||
|
|
||||||
|
return name.padEnd(10, '\u2003') + (item.value || 0)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
series: [
|
series: [
|
||||||
{
|
{
|
||||||
name: '任务分布',
|
name: '任务分布',
|
||||||
type: 'pie',
|
type: 'pie',
|
||||||
radius: ['45%', '65%'],
|
radius: ['50%', '70'],
|
||||||
center: ['50%', '55%'],
|
center: ['25%', '50%'],
|
||||||
avoidLabelOverlap: false,
|
|
||||||
itemStyle: {
|
|
||||||
borderRadius: 10,
|
|
||||||
borderColor: '#fff',
|
|
||||||
borderWidth: 8
|
|
||||||
},
|
|
||||||
label: {
|
label: {
|
||||||
show: true,
|
show: false
|
||||||
position: 'outside',
|
|
||||||
formatter: '{b}\n{c}',
|
|
||||||
color: '#666',
|
|
||||||
fontSize: 12,
|
|
||||||
lineHeight: 18
|
|
||||||
},
|
},
|
||||||
labelLine: {
|
labelLine: {
|
||||||
show: true,
|
show: false
|
||||||
length: 15,
|
|
||||||
length2: 10,
|
|
||||||
smooth: true
|
|
||||||
},
|
},
|
||||||
data: [
|
data: [
|
||||||
{
|
{
|
||||||
@ -152,17 +137,15 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async getResourcesCount() {
|
async getResourcesCount() {
|
||||||
return this.$axios.get('/api/v1/accounts/pam-dashboard/',
|
return this.$axios.get('/api/v1/accounts/pam-dashboard/', {
|
||||||
{
|
params: {
|
||||||
params: {
|
total_count_gathered_account_automation: 1,
|
||||||
total_count_gathered_account_automation: 1,
|
total_count_push_account_automation: 1,
|
||||||
total_count_push_account_automation: 1,
|
total_count_backup_account_automation: 1,
|
||||||
total_count_backup_account_automation: 1,
|
total_count_risk_account: 1,
|
||||||
total_count_risk_account: 1,
|
total_count_integration_application: 1
|
||||||
total_count_integration_application: 1
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)
|
})
|
||||||
},
|
},
|
||||||
initChart() {
|
initChart() {
|
||||||
this.chart = echarts.init(this.$refs.chartRef)
|
this.chart = echarts.init(this.$refs.chartRef)
|
||||||
@ -192,7 +175,12 @@ export default {
|
|||||||
box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
|
box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
padding: 16px 20px 0;
|
padding: 1.25rem;
|
||||||
|
|
||||||
|
.content {
|
||||||
|
justify-content: flex-start;
|
||||||
|
padding: unset;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
@ -205,7 +193,7 @@ export default {
|
|||||||
|
|
||||||
.chart-container {
|
.chart-container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 420px;
|
height: 226px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,23 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="box">
|
<div class="card">
|
||||||
<div style="margin-bottom: 12px;">
|
<div class="title-section">
|
||||||
<Title :config="config" />
|
<Title :config="config" />
|
||||||
</div>
|
</div>
|
||||||
<div class="content">
|
|
||||||
<el-row justify="space-between" type="flex">
|
<div class="metrics-section">
|
||||||
<el-col v-for="item of summaryItems" :key="item.title" :md="8" :sm="12" :xs="12">
|
<template v-for="item of summaryItems">
|
||||||
|
<SummaryCard
|
||||||
|
:key="item.title"
|
||||||
|
:body="item.body"
|
||||||
|
:title="item.title"
|
||||||
|
class="metric-item"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<!-- <el-row :gutter="20">
|
||||||
|
<el-col v-for="item of summaryItems" :key="item.title" :md="6" :sm="12" :xs="12">
|
||||||
<SummaryCard :body="item.body" :title="item.title" />
|
<SummaryCard :body="item.body" :title="item.title" />
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row> -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -38,10 +47,10 @@ export default {
|
|||||||
summaryItems() {
|
summaryItems() {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
title: this.$t('LongTimeNoLogin'),
|
title: this.$t('LeakedPassword'),
|
||||||
body: {
|
body: {
|
||||||
route: { name: `SessionList`, params: { activeMenu: 'OnlineList' }},
|
count: this.counter.total_leaked_password_accounts,
|
||||||
count: this.counter.total_long_time_no_login_accounts
|
disabled: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -51,6 +60,14 @@ export default {
|
|||||||
disabled: true
|
disabled: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: this.$t('LongTimeNoLogin'),
|
||||||
|
body: {
|
||||||
|
route: { name: `SessionList`, params: { activeMenu: 'OnlineList' }},
|
||||||
|
count: this.counter.total_long_time_no_login_accounts
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
title: this.$t('LongTimeNoChangeSecret'),
|
title: this.$t('LongTimeNoChangeSecret'),
|
||||||
body: {
|
body: {
|
||||||
@ -58,19 +75,24 @@ export default {
|
|||||||
disabled: true
|
disabled: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
title: this.$t('LeakedPassword'),
|
|
||||||
body: {
|
|
||||||
count: this.counter.total_leaked_password_accounts,
|
|
||||||
disabled: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: this.$t('RepeatedPassword'),
|
title: this.$t('RepeatedPassword'),
|
||||||
body: {
|
body: {
|
||||||
count: this.counter.total_repeated_password_accounts,
|
count: this.counter.total_repeated_password_accounts,
|
||||||
disabled: true
|
disabled: true
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Unmanaged'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Password expiration'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Wrong password'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'No admin'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -100,34 +122,49 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.box {
|
.card {
|
||||||
padding: 20px;
|
display: flex;
|
||||||
background: #FFFFFF;
|
flex-direction: column;
|
||||||
|
gap: 1.25rem;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
padding: 1.25rem;
|
||||||
|
background-color: #FFF;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
.content {
|
.metrics-section {
|
||||||
.el-col {
|
display: flex;
|
||||||
padding-left: 16px;
|
flex-wrap: wrap;
|
||||||
border-left: 1px solid #EFF0F1;
|
row-gap: 1.25rem;
|
||||||
|
|
||||||
&:first-child {
|
.metric-item {
|
||||||
padding-left: 0;
|
width: 25%;
|
||||||
border-left: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.sub {
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 400;
|
|
||||||
font-size: 12px;
|
|
||||||
line-height: 20px;
|
|
||||||
color: #646A73;
|
|
||||||
}
|
|
||||||
|
|
||||||
.num {
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 500;
|
|
||||||
font-size: 24px;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease-in-out;
|
||||||
|
|
||||||
|
::v-deep .summary-header {
|
||||||
|
.title {
|
||||||
|
color: #646A73;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 1.4rem;
|
||||||
|
text-transform: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 span {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transform: translateY(-0.2rem);
|
||||||
|
|
||||||
|
::v-deep .no-margins {
|
||||||
|
.num {
|
||||||
|
color: var(--color-primary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<el-divider />
|
||||||
|
|
||||||
<div class="metrics-section">
|
<div class="metrics-section">
|
||||||
<div
|
<div
|
||||||
v-for="item in summaryItems"
|
v-for="item in summaryItems"
|
||||||
@ -76,12 +78,17 @@ export default {
|
|||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
$text-color: #646A73;
|
$text-color: #646A73;
|
||||||
|
|
||||||
|
.el-divider--horizontal {
|
||||||
|
margin: unset !important;
|
||||||
|
}
|
||||||
|
|
||||||
.card {
|
.card {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 1.25rem;
|
gap: 1.25rem;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
padding: 1.25rem;
|
||||||
background-color: #FFF;
|
background-color: #FFF;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
|
@ -2,34 +2,28 @@
|
|||||||
<Page>
|
<Page>
|
||||||
<div v-if="this.$hasPerm('rbac.view_console')">
|
<div v-if="this.$hasPerm('rbac.view_console')">
|
||||||
<Announcement />
|
<Announcement />
|
||||||
<div class="dashboard-container">
|
|
||||||
<el-row :gutter="20" class="top-summary">
|
<div class="summary-container">
|
||||||
<el-col :lg="16" :xs="24" class="left-column">
|
<el-row :gutter="20">
|
||||||
<div class="mission-wrapper">
|
<el-col :span="16">
|
||||||
<DataSummary class="summary-card" />
|
<DataSummary class="data-summery" />
|
||||||
</div>
|
|
||||||
<div class="account-wrapper">
|
|
||||||
<AccountSummary class="summary-card" />
|
|
||||||
</div>
|
|
||||||
<div class="risk-wrapper">
|
|
||||||
<RiskSummary class="summary-card" />
|
|
||||||
</div>
|
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :lg="8" :xs="24" class="right-column">
|
<el-col :span="8">
|
||||||
<MissionSummery class="summary-card" />
|
<AccountSecretSummary class="account-secret-summary" />
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<el-row :gutter="20" class="middle-section">
|
<el-row :gutter="20">
|
||||||
<el-col :span="24">
|
<el-col :span="16">
|
||||||
<AccountSecretSummary class="secret-summary" />
|
<RiskSummary class="risk-summary" />
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="8">
|
||||||
|
<MissionSummery class="mission-summery" />
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<el-row :gutter="20" class="bottom-section">
|
<el-row>
|
||||||
<el-col :span="24" class="asset-proportion-wrapper">
|
<AssetProportionSummary :url="url" class="asset-proportion-summary" />
|
||||||
<AssetProportionSummary :url="url" class="summary-card" />
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
</el-row>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -43,7 +37,6 @@ import { Announcement } from '@/components'
|
|||||||
import Page403 from '@/views/403'
|
import Page403 from '@/views/403'
|
||||||
import DataSummary from './DataSummary'
|
import DataSummary from './DataSummary'
|
||||||
import RiskSummary from './RiskSummary.vue'
|
import RiskSummary from './RiskSummary.vue'
|
||||||
import AccountSummary from './AccountSummary.vue'
|
|
||||||
import AssetProportionSummary from './AssetProportionSummary'
|
import AssetProportionSummary from './AssetProportionSummary'
|
||||||
import MissionSummery from './MissionSummery.vue'
|
import MissionSummery from './MissionSummery.vue'
|
||||||
import AccountSecretSummary from '../ChangeSecret/AccountSummary.vue'
|
import AccountSecretSummary from '../ChangeSecret/AccountSummary.vue'
|
||||||
@ -57,7 +50,6 @@ export default {
|
|||||||
RiskSummary,
|
RiskSummary,
|
||||||
Announcement,
|
Announcement,
|
||||||
MissionSummery,
|
MissionSummery,
|
||||||
AccountSummary,
|
|
||||||
AccountSecretSummary,
|
AccountSecretSummary,
|
||||||
AssetProportionSummary
|
AssetProportionSummary
|
||||||
},
|
},
|
||||||
@ -70,80 +62,31 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.dashboard-container {
|
.el-row {
|
||||||
.top-summary,
|
margin-bottom: 1.25rem;
|
||||||
.middle-section,
|
}
|
||||||
.bottom-section {
|
|
||||||
margin-bottom: 1.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.top-summary {
|
.summary-container {
|
||||||
.left-column {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 1.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.right-column {
|
.account-secret-summary,
|
||||||
max-height: 540px;
|
.asset-proportion-summary,
|
||||||
height: 540px;
|
.risk-summary,
|
||||||
|
.mission-summery {
|
||||||
::v-deep .el-row,
|
|
||||||
::v-deep .el-col {
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.bottom-section {
|
|
||||||
.data-summary-wrapper {
|
|
||||||
margin-bottom: 1.25rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.summary-card {
|
|
||||||
background: #fff;
|
|
||||||
padding: 1.25rem;
|
|
||||||
height: 100%;
|
|
||||||
box-shadow: 0 1px 4px rgba(0, 21, 41, .08);
|
|
||||||
transition: all .3s;
|
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
::v-deep .card-content {
|
.account-secret-summary,
|
||||||
padding-bottom: unset;
|
.asset-proportion-summary {
|
||||||
border-bottom: unset;
|
margin-top: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep .ring {
|
.account-secret-summary {
|
||||||
display: none;
|
margin-top: unset;
|
||||||
|
|
||||||
|
::v-deep .echarts {
|
||||||
|
height: 205px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.mission-summary {
|
|
||||||
background: #fff;
|
|
||||||
padding: 1.25rem;
|
|
||||||
box-shadow: 0 1px 4px rgba(0, 21, 41, .08);
|
|
||||||
}
|
|
||||||
|
|
||||||
.secret-summary {
|
|
||||||
background: #fff;
|
|
||||||
padding: 1.25rem;
|
|
||||||
margin-bottom: 1.25rem;
|
|
||||||
box-shadow: 0 1px 4px rgba(0, 21, 41, .08);
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: 1200px) {
|
|
||||||
.right-column {
|
|
||||||
margin-top: 1.25rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: 768px) {
|
|
||||||
padding: 0.625rem;
|
|
||||||
|
|
||||||
.el-col {
|
|
||||||
margin-bottom: 1.25rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
Loading…
Reference in New Issue
Block a user