Skip to content

Commit

Permalink
feat(status): add numeric cards
Browse files Browse the repository at this point in the history
  • Loading branch information
shigma committed Mar 16, 2021
1 parent 5ff956f commit bd33be6
Show file tree
Hide file tree
Showing 8 changed files with 121 additions and 25 deletions.
49 changes: 49 additions & 0 deletions packages/plugin-status/client/components/card-numeric.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<template>
<k-card class="k-card-numeric">
<i :class="`fas fa-${icon}`"/>
<div class="content">
<p class="title">{{ title }}</p>
<p class="value"><slot/></p>
</div>
</k-card>
</template>

<script lang="ts" setup>
import { defineProps } from 'vue'
defineProps<{
title: string
icon: string
to?: string
}>()
</script>

<style lang="scss" scoped>
.k-card-numeric {
i {
font-size: 2.4rem;
padding: 0.3rem 0;
width: 3rem;
text-align: center;
}
.content {
float: right;
text-align: right;
}
p {
margin: 0;
}
.value {
font-size: 1.2rem;
margin-top: 0.2rem;
color: rgba(244, 244, 245, .8);
}
}
</style>
13 changes: 6 additions & 7 deletions packages/plugin-status/client/components/card.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
<template>
<section class="k-card">
<header><slot name="header">{{ title }}</slot></header>
<header v-if="title || $slots.header">
<slot name="header">{{ title }}</slot>
</header>
<div class="k-card-body"><slot/></div>
</section>
</template>
Expand All @@ -23,20 +25,21 @@ $paddingY: 1.6rem;
.k-card {
max-width: 960px;
margin: 0 auto;
width: 100%;
border-radius: 6px;
background: rgba(0, 0, 0, .24);
box-shadow: 0 23px 20px -20px rgb(9 10 18 / 10%), 0 0 15px rgb(9 10 18 / 6%);
header {
font-size: 1.25rem;
font-weight: bolder;
padding: $paddingX $paddingY;
padding: $paddingX $paddingY 0;
transition: color 0.3s ease;
color: rgba(244, 244, 245, .8);
}
.k-card-body {
padding: 0 $paddingY $paddingX;
padding: $paddingX $paddingY;
}
&.frameless .k-card-body {
Expand All @@ -50,10 +53,6 @@ $paddingY: 1.6rem;
.footer {
border-top: 1px solid #EBEEF5;
}
& + & {
margin-top: 2rem;
}
}
</style>
24 changes: 19 additions & 5 deletions packages/plugin-status/client/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { ElButton, ElCollapseTransition } from 'element-plus'
import { THEME_KEY } from 'vue-echarts'
import { createRouter, createWebHistory } from 'vue-router'
import Card from './components/card.vue'
import CardNumeric from './components/card-numeric.vue'
import App from './views/layout/index.vue'
import { status } from '.'

Expand All @@ -20,21 +21,34 @@ import './index.scss'
declare module 'vue-router' {
interface RouteMeta {
icon?: string
status?: boolean
}
}

const app = createApp(App)

const router = createRouter({
history: createWebHistory(),
routes: [
{ path: '/', name: '仪表盘', meta: { icon: 'tachometer-alt' }, component: () => import('./views/home/index.vue') },
{ path: '/bots', name: '机器人', meta: { icon: 'robot' }, component: () => import('./views/bots.vue') },
{ path: '/plugins', name: '插件', meta: { icon: 'plug' }, component: () => import('./views/plugins/index.vue') },
],
routes: [{
path: '/',
name: '仪表盘',
meta: { icon: 'tachometer-alt' },
component: () => import('./views/home/index.vue'),
}, {
path: '/bots',
name: '机器人',
meta: { icon: 'robot' },
component: () => import('./views/bots.vue'),
}, {
path: '/plugins',
name: '插件',
meta: { icon: 'plug' },
component: () => import('./views/plugins/index.vue'),
}],
})

app.component('k-card', Card)
app.component('k-card-numeric', CardNumeric)

app.provide(THEME_KEY, 'light')

Expand Down
3 changes: 1 addition & 2 deletions packages/plugin-status/client/views/bots.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<k-card v-if="status" class="bot-table" title="账号数据">
<k-card class="bot-table" title="账号数据">
<table v-if="status.bots.length">
<tr>
<th>平台名</th>
Expand All @@ -23,7 +23,6 @@
<script lang="ts" setup>
import { status } from '~/client'
import { defineProps } from 'vue'
const codes = ['运行中', '闲置', '离线', '网络异常', '服务器异常', '封禁中', '尝试连接']
Expand Down
41 changes: 34 additions & 7 deletions packages/plugin-status/client/views/home/index.vue
Original file line number Diff line number Diff line change
@@ -1,20 +1,47 @@
<template>
<template v-if="status">
<load-chart :status="status"/>
<history-chart :status="status"/>
<hour-chart :status="status"/>
<group-chart :status="status"/>
<word-cloud :status="status"/>
</template>
<div class="basic-stats">
<k-card-numeric title="当前消息频率" icon="paper-plane">{{ upRate }} / min</k-card-numeric>
<k-card-numeric title="近期消息频率" icon="history">{{ recentRate }} / d</k-card-numeric>
<k-card-numeric title="命名插件数量" icon="plug">{{ status.pluginCount }}</k-card-numeric>
<k-card-numeric title="数据库体积" icon="database">456 MB</k-card-numeric>
<k-card-numeric title="活跃用户数量" icon="heart">456</k-card-numeric>
<k-card-numeric title="活跃群数量" icon="users">32</k-card-numeric>
</div>
<load-chart :status="status"/>
<history-chart :status="status"/>
<hour-chart :status="status"/>
<group-chart :status="status"/>
<word-cloud :status="status"/>
</template>

<script setup lang="ts">
import { computed } from 'vue'
import { status } from '~/client'
import GroupChart from './group-chart.vue'
import HistoryChart from './history-chart.vue'
import HourChart from './hour-chart.vue'
import LoadChart from './load-chart.vue'
import WordCloud from './word-cloud.vue'
const upRate = computed(() => {
return status.value.bots.reduce((sum, bot) => sum + bot.currentRate[0], 0)
})
const recentRate = computed(() => {
return status.value.bots.reduce((sum, bot) => sum + bot.recentRate[0], 0)
})
</script>

<style lang="scss">
.basic-stats {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(2, 1fr);
grid-gap: 2rem;
margin-bottom: 2rem;
}
</style>
6 changes: 5 additions & 1 deletion packages/plugin-status/client/views/layout/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,14 @@
</ul>
</aside>
<main>
<router-view/>
<router-view v-if="status"/>
</main>
</template>

<script lang="ts" setup>
import { status } from '~/client'
</script>

<style lang="scss">
Expand All @@ -32,6 +35,7 @@ body {
color: rgba(244, 244, 245, .6);
overflow-x: hidden;
background: radial-gradient(farthest-side ellipse at 10% 0, #333867, #17193b);
background-attachment: fixed;
position: relative;
}
Expand Down
2 changes: 1 addition & 1 deletion packages/plugin-status/server/stats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ async function download(ctx: Context, date: Date) {
name: name || key,
value: messageMap[key],
last: daily[0].group[key],
assignee: ctx.bots[assignee].selfId,
assignee: ctx.bots[`${platform}:${assignee}`].selfId,
})
}
}
Expand Down
8 changes: 6 additions & 2 deletions packages/plugin-status/server/webui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export interface PluginData extends Plugin.Meta {

export interface Payload extends Profile, Statistics {
plugins: PluginData[]
pluginCount: number
}

export const name = 'webui'
Expand Down Expand Up @@ -64,7 +65,7 @@ export function apply(ctx: Context, config: Config = {}) {
if (!profile) await updateProfile()
const data = JSON.stringify({
type: 'update',
body: { ...profile, plugins },
body: { ...profile, plugins, pluginCount },
})
socket.send(data)
})
Expand All @@ -87,24 +88,27 @@ export function apply(ctx: Context, config: Config = {}) {
const children = state.children.flatMap(traverse, 1)
const { name, sideEffect } = state
if (!name) return children
pluginCount += 1
const dependencies = [...new Set(getDeps(state))]
return [{ name, sideEffect, children, dependencies }]
}

let plugins: PluginData[]
let pluginCount: number
let profile: Profile

async function broadcast(callback: () => void | Promise<void>) {
if (!wsServer?.clients.size) return
await callback()
const data = JSON.stringify({
type: 'update',
body: { ...profile, plugins },
body: { ...profile, plugins, pluginCount },
})
wsServer.clients.forEach((socket) => socket.send(data))
}

function updatePlugins() {
pluginCount = 0
plugins = traverse(null)
}

Expand Down

0 comments on commit bd33be6

Please sign in to comment.