[Update] 添加dashboard

This commit is contained in:
ibuler
2020-05-19 19:57:26 +08:00
parent 9cf93cbc52
commit 03450c05ed
14 changed files with 600 additions and 36 deletions

View File

@@ -20,6 +20,7 @@
"dependencies": {
"axios": "0.18.1",
"deepmerge": "^4.2.2",
"echarts": "^4.7.0",
"element-ui": "2.13.0",
"eslint-plugin-html": "^6.0.0",
"jquery": "^3.5.0",
@@ -41,6 +42,7 @@
"normalize.css": "7.0.0",
"nprogress": "0.2.0",
"path-to-regexp": "2.4.0",
"v-charts": "^1.19.0",
"vue": "2.6.10",
"vue-codemirror-lite": "^1.0.4",
"vue-cookie": "^1.1.4",

View File

@@ -1,8 +1,12 @@
<template>
<el-card :class="'ibox ' + type" shadow="never" v-bind="$attrs">
<div v-if="title" slot="header" class="clearfix ibox-title">
<i v-if="fa" :class="'fa ' + fa" /> {{ title }}
</div>
<template #header>
<slot name="header">
<div v-if="title" slot="header" class="clearfix ibox-title">
<i v-if="fa" :class="'fa ' + fa" /> {{ title }}
</div>
</slot>
</template>
<slot />
</el-card>
</template>

View File

@@ -1,12 +1,21 @@
<template>
<el-card>
<div slot="header">
<span>卡片名称</span>
<span class="pull-right">卡片标签</span>
</div>
<div>
<span>卡片内容</span>
<el-card shadow="never">
<div slot="header" class="summary-header">
<span class="header-title">{{ title }}</span>
<span class="pull-right right-side">
<slot name="header-right">
<el-tag :type="rightSideLabel.type || 'success'" effect="dark" size="mini">{{ rightSideLabel.title }}</el-tag>
</slot>
</span>
</div>
<slot>
<h1 class="no-margins">
<a :href="body.link">
<span>{{ body.count }}</span>
</a>
</h1>
<small>{{ body.comment }}</small>
</slot>
</el-card>
</template>
@@ -14,12 +23,55 @@
export default {
name: 'SummaryCard',
props: {
title: {
type: String,
default: ''
},
rightSideLabel: {
type: Object,
default: () => ({})
},
body: {
type: Object,
default: () => ({})
}
}
}
</script>
<style scoped>
<style lang="scss" scoped>
.pull-right {
float: right!important;
float: right !important;
}
.header-title {
font-size: 14px;
margin: 0 0 7px;
font-weight: 600;
}
.right-side >>> .el-tag {
font-weight: 600;
padding: 3px 8px;
text-shadow: none;
line-height: 1;
}
h1 {
font-size: 30px;
font-weight: 100;
}
.el-card__body {
background-color: #ffffff;
color: inherit;
padding: 15px 20px 20px 20px !important;
border-color: #e7eaec;
border-image: none;
border-style: solid solid none;
border-width: 1px 0;
}
.no-margins {
margin: 0 !important;
}
</style>

View File

@@ -732,5 +732,11 @@
"Assets": "",
"settings": {
"setting": ""
},
"dashboard": {
"UsersTotal": "用户总数",
"AssetsTotal": "资产总数",
"OnlineUsers": "在线用户",
"OnlineSessions": "在线会话"
}
}

View File

@@ -36,6 +36,9 @@ Vue.use(ElementUI, { locale })
Vue.config.productionTip = false
import VCharts from 'v-charts'
Vue.use(VCharts)
// cookie
import VueCookie from 'vue-cookie'
Vue.use(VueCookie)

View File

@@ -384,3 +384,20 @@ td .el-button.el-button--mini {
padding-left: 10px;
padding-right: 14px;
}
.el-tag--dark.el-tag--info {
background-color: #23c6c8;
border-color: #23c6c8;
color: #fff;
}
a {
color: #428bca !important;
text-decoration: none;
}
.el-tag--default.el-tag--dark {
background-color: #d1dade;
color: #5e5e5e;
border: none;
}

View File

@@ -71,3 +71,11 @@ div:focus {
.el-tooltip__popper.is-light.help-tips div span {
padding: 50px;
}
.white-bg {
background-color: #ffffff;
}
.small, small {
font-size: 85%;
}

View File

@@ -0,0 +1,52 @@
<template>
<div class="statistic-box">
<small>活跃用户资产占比</small>
<el-row :gutter="10">
<el-col :span="12">
<ve-pie :data="userData" :legend="legend" :grid="grid" :extend="chartExtend" :height="'200px'" />
</el-col>
<el-col :span="12">
<ve-pie :data="userData" :legend="legend" :extend="chartExtend" />
</el-col>
</el-row>
</div>
</template>
<script>
export default {
name: 'LoginActivePin',
data() {
return {
legend: {
show: false
},
grid: {
x: 0,
y: 20,
x2: 20,
y2: 30
},
chartExtend: {
series(v) {
v.forEach(i => {
i.radius = ['50%', '70%']
})
return v
}
},
userData: {
columns: ['日期', '访问用户'],
rows: [
{ '日期': '1/1', '访问用户': 1393 },
{ '日期': '1/2', '访问用户': 3530 },
{ '日期': '1/6', '访问用户': 4593 }
]
}
}
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,134 @@
<template>
<ve-line :data="chartData" :settings="chartSettings" :title="title" height="350px" />
</template>
<script>
export default {
name: 'LoginMetric',
data: function() {
return {
legend: {
y: 'bottom'
},
title: {
show: false
},
chartSettings: {
metrics: ['LoginCount', 'ActiveUser', 'ActiveAsset'],
area: true,
dimension: ['Date'],
labelMap: {
'LoginCount': '登录数量',
'ActiveUser': '活跃用户',
'ActiveAsset': '活跃资产'
}
},
chartData: {
columns: ['Date', 'LoginCount', 'ActiveUser', 'ActiveAsset'],
rows: [
{
'Date': '04-19',
'LoginCount': 20316,
'ActiveUser': 5079,
'ActiveAsset': 4323
},
{
'Date': '04-20',
'LoginCount': 35218,
'ActiveUser': 8804,
'ActiveAsset': 2079
},
{
'Date': '04-21',
'LoginCount': 12864,
'ActiveUser': 3216,
'ActiveAsset': 1666
},
{
'Date': '04-22',
'LoginCount': 37508,
'ActiveUser': 9377,
'ActiveAsset': 8837
},
{
'Date': '04-23',
'LoginCount': 11787,
'ActiveUser': 2946,
'ActiveAsset': 1417
},
{
'Date': '04-24',
'LoginCount': 37749,
'ActiveUser': 9437,
'ActiveAsset': 8567
},
{
'Date': '04-25',
'LoginCount': 28591,
'ActiveUser': 7147,
'ActiveAsset': 1492
},
{
'Date': '04-26',
'LoginCount': 28571,
'ActiveUser': 7143,
'ActiveAsset': 2969
},
{ 'Date': '04-27', 'LoginCount': 8789, 'ActiveUser': 2197, 'ActiveAsset': 852 },
{
'Date': '04-28',
'LoginCount': 11434,
'ActiveUser': 2857,
'ActiveAsset': 690
},
{ 'Date': '04-29', 'LoginCount': 2100, 'ActiveUser': 525, 'ActiveAsset': 193 },
{
'Date': '04-30',
'LoginCount': 35305,
'ActiveUser': 8826,
'ActiveAsset': 2125
},
{
'Date': '05-01',
'LoginCount': 27371,
'ActiveUser': 6842,
'ActiveAsset': 5670
},
{ 'Date': '05-02', 'LoginCount': 5433, 'ActiveUser': 905, 'ActiveAsset': 127 },
{
'Date': '05-03',
'LoginCount': 59824,
'ActiveUser': 9970,
'ActiveAsset': 9148
},
{
'Date': '05-04',
'LoginCount': 69371,
'ActiveUser': 11562,
'ActiveAsset': 2237
},
{
'Date': '05-05',
'LoginCount': 11388,
'ActiveUser': 1898,
'ActiveAsset': 1685
},
{
'Date': '05-06',
'LoginCount': 101993,
'ActiveUser': 16999,
'ActiveAsset': 13882
},
{
'Date': '05-07',
'LoginCount': 26256,
'ActiveUser': 4376,
'ActiveAsset': 829
},
{ 'Date': '05-09', 'LoginCount': 0, 'ActiveUser': 0, 'ActiveAsset': 0 },
{ 'Date': '05-11', 'LoginCount': 0, 'ActiveUser': 0, 'ActiveAsset': 0 }]
}
}
}
}
</script>

View File

@@ -0,0 +1,101 @@
<template>
<div>
<small>过去一周, 共有 2 位用户登录 31 次资产.</small>
<ul class="list-group clear-list m-t">
<li v-for="(item, index) of summaryItems" :key="item.username" class="list-group-item fist-item">
<span class="pull-right">
{{ item.count }} /
</span>
<el-tag effect="dark" size="small" :type="getLabelType(index)">{{ index + 1 }}</el-tag>
{{ item.username }}
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'LoginTop',
data() {
return {
summaryItems: [
{
username: '周杰伦',
count: 42
},
{
username: '林俊杰',
count: 30
},
{
username: '蔡依林',
count: 28
},
{
username: '梁静茹',
count: 26
},
{
username: '孙燕姿',
count: 22
}
],
tabsType: ['success', 'info', 'primary', 'default', 'info']
}
},
methods: {
getLabelType(index) {
return this.tabsType[index] || 'primary'
}
}
}
</script>
<style lang="scss" scoped>
.m-t {
margin-top: 15px;
}
.list-group {
padding-left: 0;
margin-bottom: 20px;
}
.list-group.clear-list .list-group-item {
border-top: 1px solid #e7eaec;
border-bottom: 0;
border-right: 0;
border-left: 0;
padding: 8px 0;
}
.list-group-item:first-child {
border-top-left-radius: 4px;
border-top-right-radius: 4px;
border-top: none !important;
}
.list-group-item {
background-color: inherit;
border: 1px solid #e7eaec;
display: block;
margin-bottom: -1px;
padding: 8px 15px;
position: relative;
font-size: 13px;
line-height: 18px;
}
.el-tag--small {
height: 24px;
font-size: 75%;
text-align: center;
white-space: nowrap;
vertical-align: baseline;
line-height: 16px;
margin-right: 10px;
font-weight: 600;
padding: 3px 8px;
text-shadow: none;
}
</style>

View File

@@ -0,0 +1,72 @@
<template>
<div class="white-bg dashboard-header">
<el-row>
<el-col :span="12">
<h2>登录汇总</h2>
</el-col>
<el-col :span="12">
<el-button-group style="float: right; padding: 0">
<el-button type="default" size="mini" :class="{ 'active': active === 'weekly'}" @click="changeDates('weekly')">Weekly</el-button>
<el-button type="default" size="mini" :class="{ 'active': active === 'monthly'}" @click="changeDates('monthly')">Monthly</el-button>
</el-button-group>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :md="6" :sm="24">
<LoginTop />
</el-col>
<el-col :md="12" :sm="24">
<LoginMetric style="margin-top: -40px" />
</el-col>
<el-col :md="6" :sm="24">
<LoginActivePin />
</el-col>
</el-row>
</div>
</template>
<script>
import LoginTop from './LoginTop'
import LoginMetric from './LoginMetric'
import LoginActivePin from './LoginActivePin'
export default {
name: 'DatesLoginSummary',
components: { LoginTop, 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);
}
</style>

View File

@@ -0,0 +1,80 @@
<template>
<el-row :gutter="10">
<el-col v-for="item of summaryItems" :key="item.title" :md="6" :sm="12">
<SummaryCard :title="item.title" :right-side-label="item.rightSideLabel" :body="item.body" />
</el-col>
</el-row>
</template>
<script>
import { SummaryCard } from '@/components'
export default {
name: 'ResourceSummary',
components: { SummaryCard },
data() {
return {
summaryItems: [
{
title: this.$t('dashboard.UsersTotal'),
rightSideLabel: {
title: 'Users',
type: 'success'
},
body: {
link: '',
count: 10,
comment: 'All users'
}
},
{
title: this.$t('dashboard.AssetsTotal'),
rightSideLabel: {
title: 'Assets',
type: 'info'
},
body: {
link: '',
count: 10,
comment: 'All assets'
}
},
{
title: this.$t('dashboard.OnlineUsers'),
rightSideLabel: {
title: 'Online',
type: 'primary'
},
body: {
link: '',
count: 10,
comment: 'Online users'
}
},
{
title: this.$t('dashboard.OnlineSessions'),
rightSideLabel: {
title: 'Connected',
type: 'danger'
},
body: {
link: '',
count: 10,
comment: 'Online sessions'
}
}
]
}
}
}
</script>
<style lang="scss" scoped>
.el-col {
margin-bottom: 25px;
&:last-child {
margin-bottom: 0;
}
}
</style>

View File

@@ -1,42 +1,27 @@
<template>
<Page>
<el-row :gutter="20">
<el-col :span="6"><SummaryCard /></el-col>
<el-col :span="6"><SummaryCard /></el-col>
<el-col :span="6"><SummaryCard /></el-col>
<el-col :span="6"><SummaryCard /></el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="4"><SummaryCard /></el-col>
<el-col :span="16"><SummaryCard /></el-col>
<el-col :span="4"><SummaryCard /></el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="8"><SummaryCard /></el-col>
<el-col :span="8"><SummaryCard /></el-col>
<el-col :span="8"><SummaryCard /></el-col>
</el-row>
<ResourceSummary />
<DatesLoginSummary />
</Page>
</template>
<script>
import { Page } from '@/layout/components'
import { SummaryCard } from '@/components'
import ResourceSummary from './ResourceSummary'
import DatesLoginSummary from './DatesLoginSummary'
export default {
name: 'Dashboard',
components: {
Page, SummaryCard
Page, DatesLoginSummary, ResourceSummary
},
data() {
return {
}
}
}
</script>
<style lang="scss" scoped>
.el-row {
margin-bottom: 25px;
&:last-child {
margin-bottom: 0;
}
}
</style>

View File

@@ -3331,6 +3331,28 @@ ecc-jsbn@~0.1.1:
jsbn "~0.1.0"
safer-buffer "^2.1.0"
echarts-amap@1.0.0-rc.6:
version "1.0.0-rc.6"
resolved "https://registry.npm.taobao.org/echarts-amap/download/echarts-amap-1.0.0-rc.6.tgz#5782a74daee52ed44ce3f8f62577561783f09e16"
integrity sha1-V4KnTa7lLtRM4/j2JXdWF4PwnhY=
echarts-liquidfill@^2.0.2:
version "2.0.5"
resolved "https://registry.npm.taobao.org/echarts-liquidfill/download/echarts-liquidfill-2.0.5.tgz#0d505a75c2dfb69950e18d440bdf3fe1795a0eed"
integrity sha1-DVBadcLftplQ4Y1EC98/4XlaDu0=
echarts-wordcloud@^1.1.3:
version "1.1.3"
resolved "https://registry.npm.taobao.org/echarts-wordcloud/download/echarts-wordcloud-1.1.3.tgz#07b140c8ba76b19c317b43c310f3d5dc99289ff2"
integrity sha1-B7FAyLp2sZwxe0PDEPPV3Jkon/I=
echarts@^4.7.0:
version "4.7.0"
resolved "https://registry.npm.taobao.org/echarts/download/echarts-4.7.0.tgz?cache=0&sync_timestamp=1584522755461&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fecharts%2Fdownload%2Fecharts-4.7.0.tgz#5b3875a4c2f91e3929425fabab9eace7e4098b3f"
integrity sha1-Wzh1pML5HjkpQl+rq56s5+QJiz8=
dependencies:
zrender "4.3.0"
editorconfig@^0.15.3:
version "0.15.3"
resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-0.15.3.tgz#bef84c4e75fb8dcb0ce5cee8efd51c15999befc5"
@@ -6842,6 +6864,11 @@ number-is-nan@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
numerify@1.2.9:
version "1.2.9"
resolved "https://registry.npm.taobao.org/numerify/download/numerify-1.2.9.tgz#af4696bb1d57f8d3970a615d8b0cd53d932bd559"
integrity sha1-r0aWux1X+NOXCmFdiwzVPZMr1Vk=
nwsapi@^2.0.7:
version "2.2.0"
resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7"
@@ -9525,6 +9552,11 @@ utila@^0.4.0, utila@~0.4:
version "0.4.0"
resolved "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c"
utils-lite@0.1.10:
version "0.1.10"
resolved "https://registry.npm.taobao.org/utils-lite/download/utils-lite-0.1.10.tgz#d2908c0482e23c31e6b082558540e7134ffad7d7"
integrity sha1-0pCMBILiPDHmsIJVhUDnE0/619c=
utils-merge@1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
@@ -9533,6 +9565,17 @@ uuid@^3.0.1, uuid@^3.3.2:
version "3.4.0"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
v-charts@^1.19.0:
version "1.19.0"
resolved "https://registry.npm.taobao.org/v-charts/download/v-charts-1.19.0.tgz#07b701800b159bd514264ffc8bf12b0405142da3"
integrity sha1-B7cBgAsVm9UUJk/8i/ErBAUULaM=
dependencies:
echarts-amap "1.0.0-rc.6"
echarts-liquidfill "^2.0.2"
echarts-wordcloud "^1.1.3"
numerify "1.2.9"
utils-lite "0.1.10"
validate-npm-package-license@^3.0.1:
version "3.0.4"
resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a"
@@ -10152,6 +10195,11 @@ yorkie@^2.0.0:
normalize-path "^1.0.0"
strip-indent "^2.0.0"
zrender@4.3.0:
version "4.3.0"
resolved "https://registry.npm.taobao.org/zrender/download/zrender-4.3.0.tgz#9f056121b20bbae44414d287bf6a119ff7042661"
integrity sha1-nwVhIbILuuREFNKHv2oRn/cEJmE=
ztree@^3.5.24:
version "3.5.24"
resolved "https://registry.yarnpkg.com/ztree/-/ztree-3.5.24.tgz#b63fe52981fdf2c329675cfd2772f0d147521ff1"