mirror of
https://github.com/jumpserver/lina.git
synced 2025-09-20 18:49:19 +00:00
@@ -592,6 +592,8 @@
|
|||||||
"LoginTo": "Login to",
|
"LoginTo": "Login to",
|
||||||
"LoginUsers": "Active users",
|
"LoginUsers": "Active users",
|
||||||
"Monthly": "Monthly",
|
"Monthly": "Monthly",
|
||||||
|
"CurrentConnections": "Current connections",
|
||||||
|
"TodayFailedConnections": "Connections failed today",
|
||||||
"OnlineSessions": "Online sessions",
|
"OnlineSessions": "Online sessions",
|
||||||
"OnlineUsers": "Online users",
|
"OnlineUsers": "Online users",
|
||||||
"ConnectUsers": "Connect users",
|
"ConnectUsers": "Connect users",
|
||||||
|
@@ -603,6 +603,8 @@
|
|||||||
"LoginTo": "ログインしました",
|
"LoginTo": "ログインしました",
|
||||||
"LoginUsers": "アクティブユーザー",
|
"LoginUsers": "アクティブユーザー",
|
||||||
"Monthly": "月ごと",
|
"Monthly": "月ごと",
|
||||||
|
"CurrentConnections": "現在の接続数",
|
||||||
|
"TodayFailedConnections": "今日の接続に失敗しました",
|
||||||
"OnlineSessions": "オンラインセッション",
|
"OnlineSessions": "オンラインセッション",
|
||||||
"OnlineUsers": "オンラインユーザー",
|
"OnlineUsers": "オンラインユーザー",
|
||||||
"ConnectUsers": "ユーザーの接続",
|
"ConnectUsers": "ユーザーの接続",
|
||||||
|
@@ -624,7 +624,9 @@
|
|||||||
"LoginTo": "登录了",
|
"LoginTo": "登录了",
|
||||||
"LoginUsers": "活跃用户",
|
"LoginUsers": "活跃用户",
|
||||||
"Monthly": "按月",
|
"Monthly": "按月",
|
||||||
"OnlineSessions": "在线会话",
|
"CurrentConnections": "当前连接数",
|
||||||
|
"TodayFailedConnections": "今日连接失败数",
|
||||||
|
"OnlineSessions": "在线会话数",
|
||||||
"OnlineUsers": "在线用户",
|
"OnlineUsers": "在线用户",
|
||||||
"ConnectUsers": "连接用户",
|
"ConnectUsers": "连接用户",
|
||||||
"TimesWeekUnit": "次/周",
|
"TimesWeekUnit": "次/周",
|
||||||
|
1
src/icons/svg/broken-line.svg
Normal file
1
src/icons/svg/broken-line.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 48 48"><path stroke-linejoin="round" stroke-linecap="round" stroke-width="4" stroke="#646A73" d="M41 27V15H29" data-follow-stroke="#646A73"/><path stroke-linejoin="round" stroke-linecap="round" stroke-width="4" stroke="#646A73" d="m6 37 10.338-12.5 9.847 6L41 15" data-follow-stroke="#646A73"/></svg>
|
After Width: | Height: | Size: 365 B |
65
src/views/dashboard/RankSummary.vue
Normal file
65
src/views/dashboard/RankSummary.vue
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<el-row :gutter="16">
|
||||||
|
<el-col :lg="12" :sm="24">
|
||||||
|
<RankTable v-bind="userConfig" />
|
||||||
|
</el-col>
|
||||||
|
<el-col :lg="12" :sm="24">
|
||||||
|
<RankTable v-bind="assetConfig" />
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import RankTable from './components/RankTable.vue'
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
RankTable
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
userConfig: {
|
||||||
|
title: '登录用户排名',
|
||||||
|
url: '/api/v1/index/?dates_login_times_top10_users=1',
|
||||||
|
note: '登录用户排名',
|
||||||
|
data: 'dates_login_times_top10_users',
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
prop: 'user',
|
||||||
|
label: '用户名'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'total',
|
||||||
|
label: '登录次数'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
assetConfig: {
|
||||||
|
title: '活跃资产排名',
|
||||||
|
url: '/api/v1/index/?dates_login_times_top10_assets=1',
|
||||||
|
note: '活跃资产排名',
|
||||||
|
data: 'dates_login_times_top10_assets',
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
prop: 'asset',
|
||||||
|
label: '资产名称'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'total',
|
||||||
|
label: '访问次数'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
columnsMeta: {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
@@ -7,10 +7,10 @@
|
|||||||
<div class="add">
|
<div class="add">
|
||||||
<span class="add-num">
|
<span class="add-num">
|
||||||
本周新增:0
|
本周新增:0
|
||||||
<i class="fa fa-line-chart" />
|
<svg-icon icon-class="broken-line" style="font-size: 18px;" />
|
||||||
</span>
|
</span>
|
||||||
<span class="add-icon">
|
<span class="add-icon">
|
||||||
<i class="fa fa-users" />
|
<svg-icon icon-class="users" style="font-size: 18px;" />
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -27,7 +27,10 @@ export default {
|
|||||||
RingChart
|
RingChart
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
object: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({})
|
||||||
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
用户/资产活跃情况
|
用户/资产活跃情况
|
||||||
<i class="fa fa-exclamation-circle icon" />
|
<i class="fa fa-exclamation-circle icon" />
|
||||||
</span>
|
</span>
|
||||||
<span class="time">更新时间:2022-11-17</span>
|
<!-- <span class="time">更新时间:2022-11-17</span> -->
|
||||||
</div>
|
</div>
|
||||||
<echarts
|
<echarts
|
||||||
ref="echarts"
|
ref="echarts"
|
||||||
@@ -20,8 +20,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import 'echarts/lib/chart/line'
|
// eslint-disable-next-line no-unused-vars
|
||||||
import 'echarts/lib/component/legend'
|
import * as echarts from 'echarts'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'LoginMetric',
|
name: 'LoginMetric',
|
||||||
@@ -37,8 +37,7 @@ export default {
|
|||||||
metricsData: {
|
metricsData: {
|
||||||
dates_metrics_date: [],
|
dates_metrics_date: [],
|
||||||
dates_metrics_total_count_active_assets: [],
|
dates_metrics_total_count_active_assets: [],
|
||||||
dates_metrics_total_count_active_users: [],
|
dates_metrics_total_count_active_users: []
|
||||||
dates_metrics_total_count_login: []
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -46,13 +45,11 @@ export default {
|
|||||||
themeColor() {
|
themeColor() {
|
||||||
const documentStyle = document.documentElement.style
|
const documentStyle = document.documentElement.style
|
||||||
return {
|
return {
|
||||||
primary: documentStyle.getPropertyValue('--color-primary'),
|
primary: documentStyle.getPropertyValue('--color-primary')
|
||||||
info: documentStyle.getPropertyValue('--color-info'),
|
|
||||||
success: documentStyle.getPropertyValue('--color-success')
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
options() {
|
options() {
|
||||||
const { primary, info, success } = this.themeColor
|
const { primary } = this.themeColor
|
||||||
return {
|
return {
|
||||||
title: {
|
title: {
|
||||||
show: false
|
show: false
|
||||||
@@ -84,7 +81,7 @@ export default {
|
|||||||
bottom: '3%',
|
bottom: '3%',
|
||||||
containLabel: true
|
containLabel: true
|
||||||
},
|
},
|
||||||
color: [primary, info, success],
|
color: [primary, '#F3B44B'],
|
||||||
xAxis: [
|
xAxis: [
|
||||||
{
|
{
|
||||||
type: 'category',
|
type: 'category',
|
||||||
@@ -136,13 +133,6 @@ export default {
|
|||||||
|
|
||||||
animationDuration: 500,
|
animationDuration: 500,
|
||||||
series: [
|
series: [
|
||||||
{
|
|
||||||
name: this.$t('dashboard.LoginCount'),
|
|
||||||
type: 'line',
|
|
||||||
areaStyle: {},
|
|
||||||
smooth: true,
|
|
||||||
data: this.metricsData.dates_metrics_total_count_login
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: this.$t('dashboard.LoginUsers'),
|
name: this.$t('dashboard.LoginUsers'),
|
||||||
type: 'line',
|
type: 'line',
|
||||||
@@ -171,11 +161,17 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async getMetricData() {
|
async getMetricData() {
|
||||||
let url = '/api/v1/index/?dates_metrics=1&'
|
const url = '/api/v1/index/?dates_metrics=1&'
|
||||||
if (this.range === 'monthly') {
|
const data = await this.$axios.get(url)
|
||||||
url = `${url}&monthly=1`
|
this.metricsData = data
|
||||||
|
const activeAssets = 'dates_metrics_total_count_active_assets'
|
||||||
|
const activeUsers = 'dates_metrics_total_count_active_users'
|
||||||
|
if (data[activeAssets].length < 1) {
|
||||||
|
this.metricsData[activeAssets] = [0]
|
||||||
|
}
|
||||||
|
if (data[activeUsers].length < 1) {
|
||||||
|
this.metricsData[activeUsers] = [0]
|
||||||
}
|
}
|
||||||
this.metricsData = await this.$axios.get(url)
|
|
||||||
},
|
},
|
||||||
getDataUrl() {
|
getDataUrl() {
|
||||||
this.dataUrl = this.$refs.echarts.getDataURL({
|
this.dataUrl = this.$refs.echarts.getDataURL({
|
||||||
|
167
src/views/dashboard/components/RankTable.vue
Normal file
167
src/views/dashboard/components/RankTable.vue
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
<template>
|
||||||
|
<div class="box">
|
||||||
|
<div class="head">
|
||||||
|
<span class="title">
|
||||||
|
{{ title }}
|
||||||
|
<el-tooltip
|
||||||
|
v-if="note"
|
||||||
|
effect="dark"
|
||||||
|
:content="note"
|
||||||
|
placement="top"
|
||||||
|
>
|
||||||
|
<i class="fa fa-exclamation-circle icon" />
|
||||||
|
</el-tooltip>
|
||||||
|
<i v-else class="fa fa-exclamation-circle icon" />
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
<el-radio-group
|
||||||
|
v-model="select"
|
||||||
|
class="switch"
|
||||||
|
size="mini"
|
||||||
|
@change="onChange"
|
||||||
|
>
|
||||||
|
<el-radio-button v-for="i in options" :key="i.value" :label="i.value">
|
||||||
|
{{ i.label }}
|
||||||
|
</el-radio-button>
|
||||||
|
</el-radio-group>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<el-table
|
||||||
|
:data="tableData"
|
||||||
|
style="width: 100%"
|
||||||
|
class="table"
|
||||||
|
>
|
||||||
|
<el-table-column :label="'排名'">
|
||||||
|
<template v-slot="scope">
|
||||||
|
<span>{{ scope.$index + 1 }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
v-for="i in columns"
|
||||||
|
:key="i.prop"
|
||||||
|
:prop="i.prop"
|
||||||
|
:label="i.label"
|
||||||
|
>
|
||||||
|
{{ i.prop }}
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
url: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
note: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
type: String,
|
||||||
|
default: () => ''
|
||||||
|
},
|
||||||
|
columns: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [
|
||||||
|
{
|
||||||
|
label: '今天',
|
||||||
|
value: '1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '近7天',
|
||||||
|
value: '7'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '近30天',
|
||||||
|
value: '30'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
select: '1',
|
||||||
|
tableData: [],
|
||||||
|
tableUrl: this.url + `&days=1`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.init()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
init() {
|
||||||
|
this.$axios.get(this.tableUrl).then(res => {
|
||||||
|
this.tableData = this.data ? res?.[this.data] : res
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onChange() {
|
||||||
|
this.tableUrl = this.url + `&days=${this.select}`
|
||||||
|
this.init()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.box {
|
||||||
|
margin-top: 16px;
|
||||||
|
padding: 20px;
|
||||||
|
background: #fff;
|
||||||
|
.head {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
.title {
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 26px;
|
||||||
|
color: #1F2329;
|
||||||
|
}
|
||||||
|
.icon {
|
||||||
|
color: #BBBFC4;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.switch {
|
||||||
|
background: #EFF0F1;
|
||||||
|
border-radius: 4px;
|
||||||
|
&>>> .el-radio-button {
|
||||||
|
.el-radio-button__inner {
|
||||||
|
border: none;
|
||||||
|
color: #8F959E;
|
||||||
|
background: #EFF0F1;
|
||||||
|
}
|
||||||
|
&.is-active {
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 4px 0;
|
||||||
|
.el-radio-button__inner {
|
||||||
|
color: var(--color-primary);
|
||||||
|
background-color: #FFF;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&>>> .el-radio-button__orig-radio:checked+.el-radio-button__inner {
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
>>> .el-table th, .el-table tr {
|
||||||
|
background-color: #F5F6F7!important;
|
||||||
|
}
|
||||||
|
</style>
|
@@ -2,7 +2,7 @@
|
|||||||
<div class="box">
|
<div class="box">
|
||||||
<div style="margin-bottom: 12px;">
|
<div style="margin-bottom: 12px;">
|
||||||
<span class="title">实时数据</span>
|
<span class="title">实时数据</span>
|
||||||
<span class="time">更新时间:2022-11-17</span>
|
<!-- <span class="time">更新时间:2022-11-17</span> -->
|
||||||
</div>
|
</div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<el-row type="flex" justify="space-between">
|
<el-row type="flex" justify="space-between">
|
||||||
@@ -25,10 +25,9 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
counter: {
|
counter: {
|
||||||
total_count_assets: '.',
|
total_count_online_sessions: '.',
|
||||||
total_count_users: '.',
|
|
||||||
total_count_online_users: '.',
|
total_count_online_users: '.',
|
||||||
total_count_online_sessions: '.'
|
total_count_today_failed_sessions: '.'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -36,15 +35,15 @@ export default {
|
|||||||
summaryItems() {
|
summaryItems() {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
title: this.$t('dashboard.AssetsTotal'),
|
title: this.$t('dashboard.OnlineSessions'),
|
||||||
body: {
|
body: {
|
||||||
route: { name: 'AssetList' },
|
route: { name: `SessionList`, params: { activeMenu: 'OnlineList' }},
|
||||||
count: this.counter.total_count_assets,
|
count: this.counter.total_count_online_sessions,
|
||||||
disabled: !this.$hasPerm('assets.view_asset')
|
disabled: !this.$hasPerm('terminal.view_session')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: this.$t('dashboard.ConnectUsers'),
|
title: this.$t('dashboard.CurrentConnections'),
|
||||||
body: {
|
body: {
|
||||||
route: { name: `SessionList`, params: { activeMenu: 'OnlineList' }},
|
route: { name: `SessionList`, params: { activeMenu: 'OnlineList' }},
|
||||||
count: this.counter.total_count_online_users,
|
count: this.counter.total_count_online_users,
|
||||||
@@ -52,11 +51,10 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: this.$t('dashboard.OnlineSessions'),
|
title: this.$t('dashboard.TodayFailedConnections'),
|
||||||
body: {
|
body: {
|
||||||
route: { name: `SessionList`, params: { activeMenu: 'OnlineList' }},
|
count: this.counter.total_count_today_failed_sessions,
|
||||||
count: this.counter.total_count_online_sessions,
|
disabled: true
|
||||||
disabled: !this.$hasPerm('terminal.view_session')
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@@ -2,18 +2,15 @@
|
|||||||
<Page>
|
<Page>
|
||||||
<div v-if="this.$hasPerm('rbac.view_console|rbac.view_audit')">
|
<div v-if="this.$hasPerm('rbac.view_console|rbac.view_audit')">
|
||||||
<Announcement />
|
<Announcement />
|
||||||
<!-- <ResourceSummary /> -->
|
|
||||||
<!-- <DatesLoginSummary /> -->
|
|
||||||
<el-row :gutter="16">
|
<el-row :gutter="16">
|
||||||
<el-col :lg="12" :sm="24">
|
<el-col :lg="12" :sm="24">
|
||||||
<Left />
|
<LeftSummary />
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :lg="12" :sm="24">
|
<el-col :lg="12" :sm="24">
|
||||||
<DataSummary />
|
<DataSummary />
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<TrendSummary />
|
<RankSummary />
|
||||||
<TopAndLatestSummary />
|
|
||||||
</div>
|
</div>
|
||||||
<Page403 v-else />
|
<Page403 v-else />
|
||||||
</Page>
|
</Page>
|
||||||
@@ -22,21 +19,19 @@
|
|||||||
<script>
|
<script>
|
||||||
import { Announcement } from '@/components'
|
import { Announcement } from '@/components'
|
||||||
import { Page } from '@/layout/components'
|
import { Page } from '@/layout/components'
|
||||||
import TopAndLatestSummary from './TopAndLatestSummary'
|
|
||||||
import Page403 from '@/views/403'
|
import Page403 from '@/views/403'
|
||||||
import DataSummary from './DataSummary'
|
import DataSummary from './DataSummary'
|
||||||
import Left from './Left'
|
import LeftSummary from './LeftSummary'
|
||||||
import TrendSummary from './TrendSummary'
|
import RankSummary from './RankSummary'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Dashboard',
|
name: 'Dashboard',
|
||||||
components: {
|
components: {
|
||||||
Page,
|
Page,
|
||||||
TopAndLatestSummary,
|
|
||||||
Announcement,
|
Announcement,
|
||||||
DataSummary,
|
DataSummary,
|
||||||
Left,
|
LeftSummary,
|
||||||
TrendSummary,
|
RankSummary,
|
||||||
Page403
|
Page403
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
Reference in New Issue
Block a user