perf: 调整仪表盘显示内容

This commit is contained in:
“huailei000”
2022-11-29 23:00:05 +08:00
committed by huailei
parent f79121724d
commit fc0ee3d4f8
12 changed files with 501 additions and 205 deletions

View File

@@ -0,0 +1,53 @@
<template>
<div class="box">
<div class="head">
<Title :config="titleConfig" />
</div>
<ProgressChart v-bind="config" />
</div>
</template>
<script>
import Title from './components/Title.vue'
import ProgressChart from './components/ProgressChart.vue'
export default {
components: {
Title,
ProgressChart
},
data() {
return {
titleConfig: {
title: '资产类型占比',
tip: '资产类型占比'
},
config: {
data: []
}
}
},
mounted() {
this.getChartData()
},
methods: {
async getChartData() {
const url = '/api/v1/index/?total_count_type_to_assets_amount=1'
const data = await this.$axios.get(url)
this.$set(this.config, 'data', data.total_count_type_to_assets_amount)
}
}
}
</script>
<style lang="scss" scoped>
.box {
margin-top: 16px;
padding: 20px;
background: #fff;
.head {
display: flex;
justify-content: space-between;
}
}
</style>

View File

@@ -2,10 +2,10 @@
<div> <div>
<el-row :gutter="16"> <el-row :gutter="16">
<el-col :lg="12" :sm="12"> <el-col :lg="12" :sm="12">
<DataCard /> <DataCard :config="userConfig" />
</el-col> </el-col>
<el-col :lg="12" :sm="12"> <el-col :lg="12" :sm="12">
<DataCard /> <DataCard :config="assetConfig" />
</el-col> </el-col>
</el-row> </el-row>
</div> </div>
@@ -21,15 +21,57 @@ export default {
}, },
data() { data() {
return { const documentStyle = document.documentElement.style
const themeColor = documentStyle.getPropertyValue('--color-primary')
return {
userConfig: {
title: '用户数据',
tip: '用户数据',
subTitle: '用户总数',
color: '#FFD260',
chartTitle: '今日登录用户数',
data: []
},
assetConfig: {
title: '资产数据',
tip: '资产数据',
subTitle: '资产总数',
color: themeColor,
chartTitle: '今日活跃资产数',
data: []
}
} }
}, },
created() { mounted() {
this.init()
}, },
methods: { methods: {
async init() {
const data = await this.$axios.get(`/api/v1/index/?total_count_users=1
&total_count_users_this_week=1
&total_count_today_login_users=1
&total_count_assets=1
&total_count_assets_this_week=1
&total_count_today_active_assets=1
`)
const users = [
{ name: this.$t('dashboard.ActiveUser'), value: data.total_count_users },
{ name: this.$t('dashboard.DisabledUser'), value: data.total_count_today_login_users }
]
this.$set(this.userConfig, 'data', users)
this.$set(this.userConfig, 'total', data.total_count_users)
this.$set(this.userConfig, 'active', data.total_count_today_login_users)
this.$set(this.userConfig, 'weekAdd', data.total_count_users_this_week)
const assets = [
{ name: this.$t('dashboard.ActiveUser'), value: data.total_count_assets },
{ name: this.$t('dashboard.DisabledUser'), value: data.total_count_today_active_assets }
]
this.$set(this.assetConfig, 'data', assets)
this.$set(this.assetConfig, 'total', data.total_count_assets)
this.$set(this.assetConfig, 'active', data.total_count_today_active_assets)
this.$set(this.assetConfig, 'weekAdd', data.total_count_assets_this_week)
}
} }
} }
</script> </script>

View File

@@ -1,35 +0,0 @@
<template>
<div>
<RealTimeSummary />
<LineChart />
</div>
</template>
<script>
import RealTimeSummary from './components/RealTimeSummary.vue'
import LineChart from './components/LineChart.vue'
export default {
components: {
RealTimeSummary,
LineChart
},
props: {
},
data() {
return {
}
},
created() {
},
methods: {
}
}
</script>
<style scoped>
</style>

View File

@@ -2,10 +2,10 @@
<div> <div>
<el-row :gutter="16"> <el-row :gutter="16">
<el-col :lg="12" :sm="24"> <el-col :lg="12" :sm="24">
<RankTable v-bind="userConfig" /> <RankTable :config="userConfig" />
</el-col> </el-col>
<el-col :lg="12" :sm="24"> <el-col :lg="12" :sm="24">
<RankTable v-bind="assetConfig" /> <RankTable :config="assetConfig" />
</el-col> </el-col>
</el-row> </el-row>
</div> </div>
@@ -22,7 +22,7 @@ export default {
userConfig: { userConfig: {
title: '登录用户排名', title: '登录用户排名',
url: '/api/v1/index/?dates_login_times_top10_users=1', url: '/api/v1/index/?dates_login_times_top10_users=1',
note: '登录用户排名', tip: '登录用户排名',
data: 'dates_login_times_top10_users', data: 'dates_login_times_top10_users',
columns: [ columns: [
{ {
@@ -38,7 +38,7 @@ export default {
assetConfig: { assetConfig: {
title: '活跃资产排名', title: '活跃资产排名',
url: '/api/v1/index/?dates_login_times_top10_assets=1', url: '/api/v1/index/?dates_login_times_top10_assets=1',
note: '活跃资产排名', tip: '活跃资产排名',
data: 'dates_login_times_top10_assets', data: 'dates_login_times_top10_assets',
columns: [ columns: [
{ {
@@ -50,12 +50,8 @@ export default {
label: '访问次数' label: '访问次数'
} }
] ]
}, }
columnsMeta: {}
} }
},
methods: {
} }
} }
</script> </script>

View File

@@ -1,12 +1,14 @@
<template> <template>
<div class="card"> <div class="card">
<div> <div>
<div class="title">标题</div> <div class="title">
<div class="sub">二标题11111</div> <Title :config="config" />
<div class="num">1231231213</div> </div>
<div class="sub">{{ config.subTitle }}</div>
<div class="num">{{ config.total }}</div>
<div class="add"> <div class="add">
<span class="add-num"> <span class="add-num">
本周新增0 本周新增{{ config.weekAdd }}
<svg-icon icon-class="broken-line" style="font-size: 18px;" /> <svg-icon icon-class="broken-line" style="font-size: 18px;" />
</span> </span>
<span class="add-icon"> <span class="add-icon">
@@ -15,33 +17,28 @@
</div> </div>
</div> </div>
<div class="ring"> <div class="ring">
<RingChart /> <RingChart :config="config" />
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import Title from './Title.vue'
import RingChart from './RingChart' import RingChart from './RingChart'
export default { export default {
components: { components: {
Title,
RingChart RingChart
}, },
props: { props: {
object: { config: {
type: Object, type: Object,
default: () => ({}) default: () => ({})
} }
}, },
data() { data() {
return { return {
} }
},
created() {
},
methods: {
} }
} }
</script> </script>
@@ -53,10 +50,6 @@ export default {
background-color: #FFF; background-color: #FFF;
.title { .title {
margin-bottom: 12px; margin-bottom: 12px;
line-height: 26px;
font-weight: 500;
font-size: 16px;
color: #1F2329;
} }
.sub { .sub {
font-weight: 400; font-weight: 400;
@@ -78,7 +71,7 @@ export default {
border-bottom: 1px solid #EFF0F1; border-bottom: 1px solid #EFF0F1;
} }
.ring { .ring {
padding: 26px 43px 10px; padding: 26px 0 10px;
& >>> .echarts { & >>> .echarts {
width: 100%!important; width: 100%!important;
height: 272px!important; height: 272px!important;

View File

@@ -1,11 +1,7 @@
<template> <template>
<div class="box"> <div class="box">
<div class="head"> <div class="head">
<span class="title"> <Title :config="config" />
用户/资产活跃情况
<i class="fa fa-exclamation-circle icon" />
</span>
<!-- <span class="time">更新时间2022-11-17</span> -->
</div> </div>
<echarts <echarts
ref="echarts" ref="echarts"
@@ -22,9 +18,11 @@
<script> <script>
// eslint-disable-next-line no-unused-vars // eslint-disable-next-line no-unused-vars
import * as echarts from 'echarts' import * as echarts from 'echarts'
import Title from './Title.vue'
export default { export default {
name: 'LoginMetric', name: 'LoginMetric',
components: { Title },
props: { props: {
range: { range: {
type: String, type: String,
@@ -33,6 +31,10 @@ export default {
}, },
data: function() { data: function() {
return { return {
config: {
title: '用户/资产活跃情况 ',
tip: '用户/资产活跃情况 '
},
dataUrl: '', dataUrl: '',
metricsData: { metricsData: {
dates_metrics_date: [], dates_metrics_date: [],
@@ -136,15 +138,65 @@ export default {
{ {
name: this.$t('dashboard.LoginUsers'), name: this.$t('dashboard.LoginUsers'),
type: 'line', type: 'line',
areaStyle: {},
smooth: true, smooth: true,
areaStyle: {
// 区域填充样式
normal: {
color: new echarts.graphic.LinearGradient(
0,
0,
0,
1,
[{
offset: 0,
color: 'rgba(50, 220, 182, 0.6)'
}, {
offset: 0.6,
color: 'rgba(50, 220, 182, 0.2)'
},
{
offset: 0.8,
color: 'rgba(50, 220, 182, 0.1)'
}
],
false
),
shadowColor: 'rgba(50, 220, 182, 0.1)',
shadowBlur: 6
}
},
data: this.metricsData.dates_metrics_total_count_active_users data: this.metricsData.dates_metrics_total_count_active_users
}, },
{ {
name: this.$t('dashboard.LoginAssets'), name: this.$t('dashboard.LoginAssets'),
type: 'line', type: 'line',
areaStyle: {},
smooth: true, smooth: true,
areaStyle: {
// 区域填充样式
normal: {
color: new echarts.graphic.LinearGradient(
0,
0,
0,
1,
[{
offset: 0,
color: 'rgba(249, 199, 79, 0.6)'
}, {
offset: 0.6,
color: 'rgba(249, 199, 79, 0.2)'
},
{
offset: 0.8,
color: 'rgba(249, 199, 79, 0.1)'
}
],
false
),
shadowColor: 'rgba(249, 199, 79, 0.1)',
shadowBlur: 6
}
},
data: this.metricsData.dates_metrics_total_count_active_assets data: this.metricsData.dates_metrics_total_count_active_assets
} }
] ]
@@ -161,7 +213,7 @@ export default {
}, },
methods: { methods: {
async getMetricData() { async getMetricData() {
const url = '/api/v1/index/?dates_metrics=1&' const url = '/api/v1/index/?dates_metrics=1&days=7'
const data = await this.$axios.get(url) const data = await this.$axios.get(url)
this.metricsData = data this.metricsData = data
const activeAssets = 'dates_metrics_total_count_active_assets' const activeAssets = 'dates_metrics_total_count_active_assets'

View File

@@ -0,0 +1,176 @@
<template>
<div>
<echarts
ref="echarts"
:options="options"
:autoresize="true"
class="disabled-when-print"
/>
</div>
</template>
<script>
// eslint-disable-next-line no-unused-vars
import * as echarts from 'echarts'
export default {
props: {
colors: {
type: Array,
default: () => {
const documentStyle = document.documentElement.style
const themeColor = documentStyle.getPropertyValue('--color-primary')
return [
themeColor, '#B3D6CE', '#F3B44B', 'rgba(243, 180, 75, 0.5)',
'#535C65', 'rgba(83, 92, 101, 0.5)', '#29448A', 'rgba(41, 68, 138, 0.5)'
]
}
},
data: {
type: Array,
default: () => []
}
},
data() {
return {
}
},
computed: {
options() {
const seriesList = []
const num = this.data.reduce((a, b) => a + b.total, 0)
const labels = this.data.map(item => item.label)
for (let i = 0; i < this.data.length; i++) {
const current = this.data[i]
seriesList.push({
type: 'bar',
stack: '2',
barWidth: 32,
name: current.label,
itemStyle: {
borderRadius: 0
},
data: [{
value: ((current.total / num) * 100).toFixed(2),
itemStyle: {
color: this.colors[i]
}
}],
color: this.colors[i]
})
}
return {
legend: {
left: 'auto',
icon: 'rect',
itemWidth: 10,
itemHeight: 10,
textStyle: {
color: '#000',
lineHeight: 30
},
data: labels
},
color: [
{
colorStops: [
{
offset: 0,
color: '#0176ff'
},
{
offset: 1,
color: '#0093ff'
}
],
x: 0,
y: 0,
x2: 1,
y2: 0,
type: 'linear',
global: false
}, {
colorStops: [
{
offset: 0,
color: '#9700ff'
},
{
offset: 1,
color: '#9700ff'
}
],
x: 0,
y: 0,
x2: 1,
y2: 0,
type: 'linear',
global: false
}
],
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow',
color: 'red'
},
formatter: () => {
let tip = ''
for (let i = 0; i < this.data.length; i++) {
const current = this.data[i]
tip += current.label + '' + current.total + '<br/>'
}
return tip
}
},
grid: {
top: '0%',
containLabel: true,
bottom: '-50%',
left: '0%',
right: '0%'
},
series: seriesList,
xAxis: {
type: 'value',
axisLabel: {
show: false
},
axisLine: {
show: false
},
axisTick: {
show: false
},
splitLine: {
show: false
}
},
yAxis: {
type: 'category',
axisTick: {
show: false
},
data: [''],
axisLabel: {
show: false
},
axisLine: {
show: false
},
splitLine: {
show: false
}
}
}
}
}
}
</script>
<style lang="scss" scoped>
.echarts {
width: 100%;
height: 72px;
}
</style>

View File

@@ -1,18 +1,7 @@
<template> <template>
<div class="box"> <div class="box">
<div class="head"> <div class="head">
<span class="title"> <Title :config="config" />
{{ 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> <span>
<el-radio-group <el-radio-group
v-model="select" v-model="select"
@@ -37,80 +26,66 @@
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
v-for="i in columns" v-for="i in config.columns"
:key="i.prop" :key="i.prop"
:prop="i.prop" :prop="i.prop"
:label="i.label" :label="i.label"
> />
{{ i.prop }}
</el-table-column>
</el-table> </el-table>
</div> </div>
</template> </template>
<script> <script>
import Title from './Title.vue'
export default { export default {
components: { components: {
Title
}, },
props: { props: {
title: { config: {
type: String, type: Object,
default: '' default: () => {}
}, },
url: { url: {
type: String, type: String,
default: '' 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() { data() {
const defaultOptions = [
{
label: '今天',
value: '1'
},
{
label: '近7天',
value: '7'
},
{
label: '近30天',
value: '30'
}
]
return { return {
select: '1', select: '1',
tableData: [], tableData: [],
tableUrl: this.url + `&days=1` options: this.config.options || defaultOptions,
tableUrl: this.config.url + `&days=1`
} }
}, },
created() { created() {
this.init() this.getList()
}, },
methods: { methods: {
init() { getList() {
this.$axios.get(this.tableUrl).then(res => { this.$axios.get(this.tableUrl).then(res => {
this.tableData = this.data ? res?.[this.data] : res this.tableData = this.config.data ? res?.[this.config.data] : res
}) })
}, },
onChange() { onChange() {
this.tableUrl = this.url + `&days=${this.select}` this.tableUrl = this.config.url + `&days=${this.select}`
this.init() this.getList()
} }
} }
} }
@@ -125,17 +100,6 @@ export default {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
margin-bottom: 8px; margin-bottom: 8px;
.title {
font-style: normal;
font-weight: 500;
font-size: 16px;
line-height: 26px;
color: #1F2329;
}
.icon {
color: #BBBFC4;
cursor: pointer;
}
.switch { .switch {
background: #EFF0F1; background: #EFF0F1;
border-radius: 4px; border-radius: 4px;

View File

@@ -1,8 +1,7 @@
<template> <template>
<div class="box"> <div class="box">
<div style="margin-bottom: 12px;"> <div style="margin-bottom: 12px;">
<span class="title">实时数据</span> <Title :config="config" />
<!-- <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">
@@ -15,15 +14,17 @@
</template> </template>
<script> <script>
import Title from './Title.vue'
import SummaryCard from './SummaryCard' import SummaryCard from './SummaryCard'
export default { export default {
components: { SummaryCard }, components: { Title, SummaryCard },
props: {
},
data() { data() {
return { return {
config: {
title: '实时数据',
tip: '实时数据'
},
counter: { counter: {
total_count_online_sessions: '.', total_count_online_sessions: '.',
total_count_online_users: '.', total_count_online_users: '.',
@@ -75,18 +76,6 @@ export default {
.box { .box {
padding: 20px; padding: 20px;
background: #FFFFFF; background: #FFFFFF;
.title {
font-weight: 500;
font-size: 16px;
color: #1F2329;
}
.time {
font-style: normal;
font-weight: 400;
font-size: 10px;
margin-left: 8px;
color: #8F959E;
}
.content { .content {
.el-col { .el-col {
padding-left: 16px; padding-left: 16px;

View File

@@ -17,80 +17,86 @@ export default {
}, },
props: { props: {
config: {
type: Object,
default: () => {}
}
}, },
data() { data() {
return { return {
userConnectData: {
dates_total_count_active_users: 0,
dates_total_count_disabled_users: 0,
dates_total_count_inactive_users: 0
}
} }
}, },
computed: { computed: {
themeColor() {
const documentStyle = document.documentElement.style
return {
primary: documentStyle.getPropertyValue('--color-primary'),
info: documentStyle.getPropertyValue('--color-info'),
success: documentStyle.getPropertyValue('--color-success')
}
},
options() { options() {
const { primary, info, success } = this.themeColor const { total, active, title } = this.config
const percentage = ((active / total) * 100).toFixed(0)
return { return {
title: [
{
text: this.config.chartTitle,
textStyle: {
color: '#646A73',
fontSize: 12
},
textAlign: 'center',
left: '48%',
top: '32%'
},
{
left: '48%',
top: '42%',
textAlign: 'center',
text: this.config.active,
textStyle: {
fontSize: 24,
color: '#646A73'
},
subtext: '占比' + percentage + '%',
subtextStyle: {
fontSize: 12,
color: '#646A73'
}
}
],
legend: { legend: {
show: false show: false
}, },
color: [primary, info, success], color: [this.config.color, 'rgba(43, 147, 124, 0.05)'],
tooltip: { tooltip: {
trigger: 'item', trigger: 'item',
formatter: '{a} <br/>{b}: {c} ({d}%)' formatter: '{a} <br/>{b}: {c} ({d}%)'
}, },
series: [ series: [
{ {
name: this.$t('dashboard.UserRatio'), name: title,
type: 'pie', type: 'pie',
radius: ['50%', '70%'], radius: ['72%', '90%'],
avoidLabelOverlap: false, avoidLabelOverlap: false,
label: { itemStyle: {
show: false, normal: {
position: 'center' label: {
show: false
},
labelLine: {
show: false
}
}
}, },
emphasis: { emphasis: {
label: { label: {
show: true, show: false
fontSize: '18',
fontWeight: 'bold'
} }
}, },
labelLine: { labelLine: {
show: false show: false
}, },
data: [ startAngle: 180,
{ name: this.$t('dashboard.ActiveUser'), value: this.userConnectData.dates_total_count_active_users }, data: this.config.data
{ 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 }
]
} }
] ]
} }
} }
},
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
}
} }
} }
</script> </script>

View File

@@ -0,0 +1,54 @@
<template>
<div class="content">
<span class="title">{{ config.title }}</span>
<el-tooltip
v-if="config.tip"
effect="dark"
:content="config.tip"
placement="top"
>
<i class="fa fa-exclamation-circle icon" />
</el-tooltip>
<i v-else class="fa fa-exclamation-circle icon" />
<span v-if="config.time" class="time">更新时间{{ config.time }}</span>
</div>
</template>
<script>
export default {
props: {
config: {
type: Object,
default: () => ({})
}
},
data() {
return {
}
}
}
</script>
<style lang="scss" scoped>
.content {
display: inline-block;
.title {
font-weight: 500;
font-size: 16px;
color: #1F2329;
}
.icon {
color: #BBBFC4;
font-size: 16px;
cursor: pointer;
}
.time {
font-style: normal;
font-weight: 400;
font-size: 10px;
margin-left: 8px;
color: #8F959E;
}
}
</style>

View File

@@ -4,12 +4,14 @@
<Announcement /> <Announcement />
<el-row :gutter="16"> <el-row :gutter="16">
<el-col :lg="12" :sm="24"> <el-col :lg="12" :sm="24">
<LeftSummary /> <RealTimeSummary />
<LineChart />
</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>
<AssetProportionSummary />
<RankSummary /> <RankSummary />
</div> </div>
<Page403 v-else /> <Page403 v-else />
@@ -21,8 +23,10 @@ import { Announcement } from '@/components'
import { Page } from '@/layout/components' import { Page } from '@/layout/components'
import Page403 from '@/views/403' import Page403 from '@/views/403'
import DataSummary from './DataSummary' import DataSummary from './DataSummary'
import LeftSummary from './LeftSummary' import AssetProportionSummary from './AssetProportionSummary'
import RankSummary from './RankSummary' import RankSummary from './RankSummary'
import RealTimeSummary from './components/RealTimeSummary.vue'
import LineChart from './components/LineChart.vue'
export default { export default {
name: 'Dashboard', name: 'Dashboard',
@@ -30,8 +34,10 @@ export default {
Page, Page,
Announcement, Announcement,
DataSummary, DataSummary,
LeftSummary, AssetProportionSummary,
RankSummary, RankSummary,
RealTimeSummary,
LineChart,
Page403 Page403
}, },
data() { data() {