Skip to content

Commit

Permalink
feat(status): add status plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
shigma committed May 14, 2024
1 parent fd8c224 commit 8debcd1
Show file tree
Hide file tree
Showing 17 changed files with 534 additions and 0 deletions.
9 changes: 9 additions & 0 deletions packages/status/client/bots/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Context } from '@cordisjs/client'
import Bots from './index.vue'

export default (ctx: Context) => {
ctx.slot({
type: 'status-right',
component: Bots,
})
}
78 changes: 78 additions & 0 deletions packages/status/client/bots/index.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<template>
<k-status v-if="data">
<template #tooltip>
<span v-if="!Object.values(data.bots).length" class="el-popper__empty"></span>
<template v-for="(bot, key) in data.bots" :key="key">
<bot-preview
:data="bot"
:class="{ 'has-link': bot.paths?.length }"
@click="bot.paths && router.push('/plugins/' + bot.paths[0].replace(/\./, '/'))"
></bot-preview>
</template>
</template>
<template v-for="(count, status) in statusMap" :key="status">
<template v-if="count > (config.mergeThreshold ?? 10)">
<status-light :class="status"></status-light>
<span class="count">×{{ count }}</span>
</template>
<template v-else>
<status-light v-for="(_, key) in Array(count)" :key="key" :class="status"></status-light>
</template>
</template>
<k-icon name="arrow-up"/>
<span>{{ sent }}/min</span>
<k-icon name="arrow-down"/>
<span>{{ received }}/min</span>
</k-status>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { router, Dict, useConfig, useRpc } from '@cordisjs/client'
import { getStatus } from './utils'
import BotPreview from './preview.vue'
import StatusLight from './light.vue'
import { Data } from '../../src'
const config = useConfig()
const data = useRpc<Data>()
const statusMap = computed(() => {
const map: Dict<number> = {}
for (const bot of Object.values(data.value.bots)) {
const key = getStatus(bot.status)
map[key] = (map[key] || 0) + 1
}
return Object.fromEntries(Object.entries(map)
.sort((a, b) => a[0].localeCompare(b[0])))
})
const sent = computed(() => {
return Object.values(data.value.bots).reduce((acc, bot) => acc + bot.messageSent, 0)
})
const received = computed(() => {
return Object.values(data.value.bots).reduce((acc, bot) => acc + bot.messageReceived, 0)
})
</script>
<style lang="scss" scoped>
.k-status {
.k-icon {
margin-right: 4px;
}
* + .k-icon {
margin-left: 6px;
}
.count {
margin: 0 4px 0 4px;
letter-spacing: 1px;
}
}
</style>
32 changes: 32 additions & 0 deletions packages/status/client/bots/light.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<template>
<span class="status-light"></span>
</template>

<style lang="scss" scoped>
$size: 0.625rem;
.status-light {
border-radius: $size;
transition: var(--color-transition);
width: $size;
height: $size;
&.online {
background-color: var(--k-color-success);
}
&.connect, &.reconnect {
background-color: var(--k-color-warning);
}
&.error {
background-color: var(--k-color-danger) !important;
}
&.offline {
background-color: var(--k-color-disabled);
}
& + & {
margin-left: 4px;
}
}
</style>
114 changes: 114 additions & 0 deletions packages/status/client/bots/preview.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
<template>
<section class="bot-view">
<div class="avatar" :style="{ backgroundImage: `url(${data.user!.avatar})` }" @click="$emit('avatar-click')">
<el-tooltip :content="statusNames[data.status]" placement="right">
<status-light :class="getStatus(data.status)"></status-light>
</el-tooltip>
</div>
<div class="info">
<div class="truncate" :title="data.user!.name"><k-icon name="robot"/>{{ data.user!.name }}</div>
<div class="truncate" :title="data.platform"><k-icon name="platform"/>{{ data.platform }}</div>
<div class="truncate cur-frequency">
<span style="margin-right: 8px">
<k-icon name="arrow-up"/>
<span>{{ data.messageSent }}/min</span>
</span>
<span>
<k-icon name="arrow-down"/>
<span>{{ data.messageReceived }}/min</span>
</span>
</div>
</div>
</section>
</template>

<script lang="ts" setup>
import { Status } from '@satorijs/protocol'
import type { Data } from '../../src'
import { getStatus } from './utils'
import StatusLight from './light.vue'
const statusNames: Record<Status, string> = {
[Status.ONLINE]: '运行中',
[Status.OFFLINE]: '离线',
[Status.CONNECT]: '正在连接',
[Status.RECONNECT]: '正在重连',
[Status.DISCONNECT]: '正在断开',
}
defineProps<{
data: Data.Bot
}>()
</script>

<style scoped lang="scss">
.bot-view {
width: 15rem;
padding: 0.75rem 1rem;
font-size: 14px;
display: flex;
transition: 0.3s ease;
& + & {
border-top: 1px solid var(--k-color-divider);
}
&.active {
> div.avatar {
border-color: var(--active);
}
}
> div.avatar {
position: relative;
width: 4rem;
height: 4rem;
box-sizing: content-box;
border: 1px solid var(--k-color-divider);
transition: border 0.3s ease;
border-radius: 100%;
background-size: 100%;
background-repeat: no-repeat;
transition: 0.1s ease;
flex-shrink: 0;
$borderWidth: 1px;
.status-light {
position: absolute;
bottom: -$borderWidth;
right: -$borderWidth;
width: 0.875rem;
height: 0.875rem;
border: $borderWidth solid var(--k-color-divider);
}
}
> div.info {
flex-grow: 1;
margin-left: 1.25rem;
display: flex;
flex-direction: column;
justify-content: space-around;
overflow: hidden;
.k-icon {
width: 20px;
margin-right: 6px;
text-align: center;
vertical-align: -2px;
}
}
&.has-link {
cursor: pointer;
&:hover {
background-color: var(--bg1);
}
}
}
</style>
11 changes: 11 additions & 0 deletions packages/status/client/bots/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Status } from '@satorijs/protocol'

export function getStatus(status: Status) {
switch (status) {
case Status.OFFLINE: return 'offline'
case Status.ONLINE: return 'online'
case Status.CONNECT: return 'connect'
case Status.DISCONNECT: return 'disconnect'
case Status.RECONNECT: return 'reconnect'
}
}
40 changes: 40 additions & 0 deletions packages/status/client/config.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<template>
<template v-if="bots?.length">
<h2 class="k-schema-header">
机器人
</h2>
<div class="bots-container flex flex-wrap gap-4">
<bot-preview v-for="(bot, sid) in bots" :key="sid" :data="bot"/>
</div>
</template>
</template>
<script setup lang="ts">
import { useContext, useRpc } from '@cordisjs/client'
import { computed } from 'vue'
import {} from '@cordisjs/plugin-manager/client'
import BotPreview from './bots/preview.vue'
import { Data } from '../src'
const ctx = useContext()
const data = useRpc<Data>()
const bots = computed(() => {
return Object.values(data.value.bots || {}).filter(bot => {
return bot.paths?.includes(ctx.manager.current.value!.path)
})
})
</script>
<style scoped lang="scss">
.bots-container {
.bot-view {
background-color: var(--bg0);
border-radius: 0.5rem;
}
}
</style>
5 changes: 5 additions & 0 deletions packages/status/client/icons/arrow-down.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<template>
<svg class="k-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512">
<path fill="currentColor" d="M377.4 296.6l-168 176C204.8 477.3 198.6 480 192 480s-12.84-2.688-17.38-7.438l-168-176C-2.5 286.1-2.156 271.8 7.438 262.6c9.5-9.156 24.75-8.812 33.94 .8125L168 396.1V56.02c0-13.25 10.75-24.01 23.1-24.01S216 42.77 216 56.02v340.1l126.6-132.7c9.156-9.625 24.41-9.969 33.94-.8125C386.2 271.8 386.5 286.1 377.4 296.6z"/>
</svg>
</template>
5 changes: 5 additions & 0 deletions packages/status/client/icons/arrow-up.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<template>
<svg class="k-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512">
<path fill="currentColor" d="M6.625 215.5l168-176C179.2 34.7 185.4 32.02 192 32.02s12.84 2.688 17.38 7.438l168 176c9.125 9.594 8.781 24.78-.8125 33.94c-9.5 9.156-24.75 8.812-33.94-.8125L216 115.9V456c0 13.25-10.75 23.1-23.1 23.1S168 469.3 168 456V115.9l-126.6 132.7C32.22 258.2 16.97 258.5 7.438 249.4C-2.156 240.2-2.5 225 6.625 215.5z"/>
</svg>
</template>
12 changes: 12 additions & 0 deletions packages/status/client/icons/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { icons } from '@cordisjs/client'
import ArrowUp from './arrow-up.vue'
import ArrowDown from './arrow-down.vue'
import Platform from './platform.vue'
import Pulse from './pulse.vue'
import Robot from './robot.vue'

icons.register('arrow-up', ArrowUp)
icons.register('arrow-down', ArrowDown)
icons.register('platform', Platform)
icons.register('analytic:pulse', Pulse)
icons.register('robot', Robot)
5 changes: 5 additions & 0 deletions packages/status/client/icons/platform.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<template>
<svg class="k-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<path fill="currentColor" d="M12.41 148.02l232.94 105.67c6.8 3.09 14.49 3.09 21.29 0l232.94-105.67c16.55-7.51 16.55-32.52 0-40.03L266.65 2.31a25.607 25.607 0 0 0-21.29 0L12.41 107.98c-16.55 7.51-16.55 32.53 0 40.04zm487.18 88.28l-58.09-26.33-161.64 73.27c-7.56 3.43-15.59 5.17-23.86 5.17s-16.29-1.74-23.86-5.17L70.51 209.97l-58.1 26.33c-16.55 7.5-16.55 32.5 0 40l232.94 105.59c6.8 3.08 14.49 3.08 21.29 0L499.59 276.3c16.55-7.5 16.55-32.5 0-40zm0 127.8l-57.87-26.23-161.86 73.37c-7.56 3.43-15.59 5.17-23.86 5.17s-16.29-1.74-23.86-5.17L70.29 337.87 12.41 364.1c-16.55 7.5-16.55 32.5 0 40l232.94 105.59c6.8 3.08 14.49 3.08 21.29 0L499.59 404.1c16.55-7.5 16.55-32.5 0-40z"/>
</svg>
</template>
5 changes: 5 additions & 0 deletions packages/status/client/icons/pulse.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<template>
<svg class="k-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512">
<path fill="currentColor" d="M640 240C640 248.8 632.8 256 624 256h-133.1l-60 150c-2.625 6.375-8.375 10.25-16 9.1C408 415.5 402.1 410.6 400.5 403.9l-78.75-315l-82 410.3C238.3 506.5 231.9 511.8 224.4 512H224c-7.25 0-13.75-5-15.5-12.12L147.5 256H16C7.201 256 0 248.8 0 240s7.201-15.1 16-15.1H160c7.375 0 13.75 4.993 15.5 12.12l46.75 187l82-410.3C305.8 5.5 312 .25 319.5 0c8.125 .125 14.25 4.875 16 12.12l84 336l45.63-114.1C467.5 228 473.5 224 480 224h144C632.8 224 640 231.2 640 240z"/>
</svg>
</template>
5 changes: 5 additions & 0 deletions packages/status/client/icons/robot.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<template>
<svg class="k-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512">
<path fill="currentColor" d="M32,224H64V416H32A31.96166,31.96166,0,0,1,0,384V256A31.96166,31.96166,0,0,1,32,224Zm512-48V448a64.06328,64.06328,0,0,1-64,64H160a64.06328,64.06328,0,0,1-64-64V176a79.974,79.974,0,0,1,80-80H288V32a32,32,0,0,1,64,0V96H464A79.974,79.974,0,0,1,544,176ZM264,256a40,40,0,1,0-40,40A39.997,39.997,0,0,0,264,256Zm-8,128H192v32h64Zm96,0H288v32h64ZM456,256a40,40,0,1,0-40,40A39.997,39.997,0,0,0,456,256Zm-8,128H384v32h64ZM640,256V384a31.96166,31.96166,0,0,1-32,32H576V224h32A31.96166,31.96166,0,0,1,640,256Z"/>
</svg>
</template>
31 changes: 31 additions & 0 deletions packages/status/client/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { Context, Schema } from '@cordisjs/client'
import {} from '../src'
import Bots from './bots'
import Config from './config.vue'
import './icons'

declare module '@cordisjs/client' {
interface Config {
mergeThreshold: number
}
}

export default (ctx: Context) => {
ctx.plugin(Bots)

// FIXME auto inject
ctx.inject(['manager'], (ctx) => {
ctx.slot({
type: 'plugin-details',
component: Config,
order: -500,
})
})

ctx.settings({
id: 'status',
schema: Schema.object({
mergeThreshold: Schema.number().default(10).description('当机器人的数量超过这个值时将合并显示状态指示灯。'),
}).description('机器人设置'),
})
}
11 changes: 11 additions & 0 deletions packages/status/client/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"extends": "../../../tsconfig.client",
"include": [
".",
],
"references": [
{
"path": "../tsconfig.json",
},
],
}
Loading

0 comments on commit 8debcd1

Please sign in to comment.