Skip to content

Commit

Permalink
feat(status): initialize sandbox
Browse files Browse the repository at this point in the history
  • Loading branch information
shigma committed Mar 16, 2021
1 parent e500178 commit bf99513
Show file tree
Hide file tree
Showing 15 changed files with 388 additions and 82 deletions.
9 changes: 8 additions & 1 deletion packages/koishi-core/src/adapter.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Logger, paramCase, sleep, Time } from 'koishi-utils'
import { Logger, paramCase, remove, sleep, Time } from 'koishi-utils'
import { Session } from './session'
import { App } from './app'
import WebSocket from 'ws'
Expand Down Expand Up @@ -34,6 +34,7 @@ export abstract class Adapter<P extends Platform = Platform> {
const bot = new this.Bot(this, options)
this.bots.push(bot)
this.app.bots.push(bot)
return bot
}

dispatch(session: Session) {
Expand Down Expand Up @@ -254,6 +255,12 @@ export class Bot<P extends Platform> {
}
return messageIds
}

dispose() {
const bot = this as Bot.Instance<P>
remove(this.adapter.bots, bot)
remove(this.app.bots, bot)
}
}

export namespace Bot {
Expand Down
1 change: 0 additions & 1 deletion packages/plugin-status/client/components/card.vue
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ $paddingX: 1.2rem;
$paddingY: 1.6rem;
.k-card {
max-width: 960px;
margin: 0 auto;
width: 100%;
border-radius: 6px;
Expand Down
149 changes: 149 additions & 0 deletions packages/plugin-status/client/components/input.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
<template>
<div class="k-input" :class="{ focused, disabled }">
<i v-if="prefixIcon" :class="'icon-' + prefixIcon" class="prefix"/>
<input
ref="input"
:value="modelValue"
:type="type"
:style="inputStyle"
:tabindex="tabindex"
:disabled="disabled"
:placeholder="placeholder"
:class="{
invalid,
'round-left': roundLeft,
'round-right': roundRight,
'ortho-left': orthoLeft,
'ortho-right': orthoRight,
}"
@input="onInput"
@focus="onFocus"
@blur="onBlur"
@keydown.enter.stop="$emit('enter', $event)"
/>
<i v-if="suffixIcon" :class="'icon-' + suffixIcon" class="suffix"/>
</div>
</template>

<script lang="ts" setup>
import { defineProps, ref, computed, defineEmit } from 'vue'
const props = defineProps({
prefixIcon: String,
suffixIcon: String,
placeholder: String,
disabled: Boolean,
validate: Function,
tabindex: Number,
roundLeft: Boolean,
roundRight: Boolean,
orthoLeft: Boolean,
orthoRight: Boolean,
modelValue: [ String, Number ],
type: { default: 'text' },
size: { default: 1 },
})
const focused = ref(false)
const invalid = ref(false)
const inputStyle = computed(() => ({
fontSize: props.size + 'rem',
paddingLeft: +!!(props.prefixIcon) + 1 + 'em',
paddingRight: +!!(props.suffixIcon) + 1 + 'em',
}))
const emit = defineEmit(['update:modelValue', 'focus', 'blur', 'enter'])
function onInput (event) {
if (props.validate) {
invalid.value = !props.validate(event.target.value)
}
emit('update:modelValue', event.target.value)
}
function onFocus (event) {
focused.value = true
emit('focus', event)
}
function onBlur (event) {
focused.value = false
emit('blur', event)
}
</script>

<style lang="scss" scoped>
@import '../index.scss';
.k-input {
height: 2em;
position: relative;
transition: 0.3s ease;
position: relative;
display: inline-block;
> i.prefix, > i.suffix {
color: $tpColor1;
top: 50%;
position: absolute;
margin-top: -0.5em;
}
> i.prefix {
left: 10px;
}
> i.suffix {
right: 10px;
}
> input {
padding: 0;
color: white;
width: 100%;
outline: none;
font-size: 1rem;
height: inherit;
display: inline-block;
border-radius: 0.3em;
transition: 0.3s ease;
box-sizing: border-box;
appearance: none;
background-color: transparent;
border: 1px solid $tpBorderColor1;
&:hover:not(:disabled) {
border-color: $tpBorderColor2;
background-color: $tpBgColor1;
box-shadow: 0 0 4px 1px inset $tpInsetColor;
}
&:focus:not(:disabled) {
border-color: #409eff;
background-color: $tpBgColor2;
box-shadow: 0 0 8px 2px inset $tpInsetColor;
}
&::-webkit-input-placeholder {
color: $tpColor1;
user-select: none;
}
&:hover:not(:disabled)::-webkit-input-placeholder {
color: $tpColor2;
}
&:focus:not(:disabled)::-webkit-input-placeholder {
color: $tpColor3;
}
&:disabled::-webkit-input-placeholder {
color: $tpFgColor2;
}
}
&.round > input {
border-radius: 1rem;
}
&.ortho > input {
border-radius: 0;
}
}
</style>
4 changes: 0 additions & 4 deletions packages/plugin-status/client/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,4 @@ declare module '~/client' {
export * from 'koishi-plugin-status/client'
}

declare module '~/layout' {
export * from 'koishi-plugin-status/client/app.vue'
}

declare const KOISHI_ENDPOINT: string
55 changes: 27 additions & 28 deletions packages/plugin-status/client/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,34 +10,33 @@ $success: #67c23a;
$error: #F56C6C;
$warning: #E6A23C;

.el-card {
max-width: 960px;
margin: 2rem auto;
border-radius: 6px;
// color schemes
$activeColor: #7fffd4;
$accentColor: #409eff;
$warningColor: #f56c6c;
$successColor: #67c23a;
$borderColor: #eaecef;

.el-card__header {
font-size: 1.25rem;
font-weight: bolder;
padding: 1rem 1.5rem;
text-align: center;
}
$tableBdColor: #dfe2e5;

.frameless > & .el-card__body {
padding: 0;
// transparent
$tpColor1: #c0c4cc80;
$tpColor2: #c0c4ccb0;
$tpColor3: #c0c4cc;
$tpFgColor1: #e4e7ed60;
$tpFgColor2: #e4e7ed90;
$tpFgColor3: #f2f6fcc0;
$tpFgColor4: #f2f6fc;
$tpFgColor5: #f5f8fd;
$tpBgColor0: transparent;
$tpBgColor1: #fff2;
$tpBgColor2: #fff4;
$tpBorderColor1: #dcdfe640;
$tpBorderColor2: #dcdfe680;
$tpInsetColor: #0004;

p {
margin: 1.5rem 2rem;
}
}

.footer {
border-top: 1px solid #EBEEF5;
}
}

.echarts {
width: 800px;
height: 400px;
max-width: 100%;
margin: 0 auto;
}
// breakpoints
$bp_lg: 1440px;
$bp_md: 1024px;
$bp_sm: 768px;
$bp_xs: 480px;
21 changes: 21 additions & 0 deletions packages/plugin-status/client/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,24 @@ import { ref } from 'vue'
import type { Payload } from '~/server'

export const status = ref<Payload>(null)
export const socket = ref<WebSocket>(null)

export function start() {
// eslint-disable-next-line no-undef
socket.value = new WebSocket(KOISHI_ENDPOINT)
receive('update', body => status.value = body)
}

export function send(data: any) {
socket.value.send(JSON.stringify(data))
}

export function receive<T = any>(event: string, listener: (data: T) => void) {
socket.value.onmessage = (ev) => {
const data = JSON.parse(ev.data)
if (data.type === event) {
console.log(event, data.body)
listener(data.body)
}
}
}
23 changes: 10 additions & 13 deletions packages/plugin-status/client/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ 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 Input from './components/input.vue'
import App from './views/layout/index.vue'
import { status } from '.'
import { start } from '.'

// for el-collapse-transition
import 'element-plus/lib/theme-chalk/base.css'
Expand Down Expand Up @@ -44,27 +44,24 @@ const router = createRouter({
name: '插件',
meta: { icon: 'plug' },
component: () => import('./views/plugins/index.vue'),
}, {
path: '/sandbox',
name: '沙盒',
meta: { icon: 'laptop-code' },
component: () => import('./views/sandbox.vue'),
}],
})

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

app.provide(THEME_KEY, 'light')
app.provide(THEME_KEY, 'dark-blue')

app.use(ElButton)
app.use(ElCollapseTransition)

app.use(router)

// eslint-disable-next-line no-undef
const socket = new WebSocket(KOISHI_ENDPOINT)
socket.onmessage = (ev) => {
const data = JSON.parse(ev.data)
console.log('receive', data)
if (data.type === 'update') {
status.value = data.body
}
}
start()

app.mount('#app')
48 changes: 38 additions & 10 deletions packages/plugin-status/client/views/home/index.vue
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
<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>
<card-numeric title="当前消息频率" icon="paper-plane">{{ upRate }} / min</card-numeric>
<card-numeric title="近期消息频率" icon="history">{{ recentRate }} / d</card-numeric>
<card-numeric title="命名插件数量" icon="plug">{{ status.pluginCount }}</card-numeric>
<card-numeric title="数据库体积" icon="database">456 MB</card-numeric>
<card-numeric title="活跃用户数量" icon="heart">456</card-numeric>
<card-numeric title="活跃群数量" icon="users">32</card-numeric>
</div>
<load-chart :status="status"/>
<history-chart :status="status"/>
<hour-chart :status="status"/>
<group-chart :status="status"/>
<word-cloud :status="status"/>
<div class="chart-stats">
<history-chart :status="status"/>
<hour-chart :status="status"/>
<group-chart :status="status"/>
<word-cloud :status="status"/>
</div>
</template>

<script setup lang="ts">
import { computed } from 'vue'
import { status } from '~/client'
import CardNumeric from './card-numeric.vue'
import GroupChart from './group-chart.vue'
import HistoryChart from './history-chart.vue'
import HourChart from './hour-chart.vue'
Expand All @@ -44,4 +47,29 @@ const recentRate = computed(() => {
margin-bottom: 2rem;
}
.chart-stats {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-rows: repeat(2, 1fr);
grid-gap: 2rem;
margin: 2rem 0 4rem;
.echarts {
width: 600px;
height: 400px;
max-width: 100%;
margin: 0 auto -3rem;
}
@media screen and (max-width: 1440px) {
grid-template-columns: 1fr;
grid-template-rows: repeat(4, 1fr);
.echarts {
width: 800px;
height: 400px;
}
}
}
</style>

0 comments on commit bf99513

Please sign in to comment.