Skip to content

Commit

Permalink
feat(status): add group chart
Browse files Browse the repository at this point in the history
  • Loading branch information
shigma committed Mar 12, 2021
1 parent bf18011 commit cbe38c3
Show file tree
Hide file tree
Showing 9 changed files with 76 additions and 26 deletions.
3 changes: 2 additions & 1 deletion packages/plugin-status/client/app.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@
<bot-table :status="status"/>
<plugin-list :status="status"/>
<hour-chart :status="status"/>
<group-chart :status="status"/>
</template>
</template>

<script setup lang="ts">
import { useStatus, BotTable, HourChart, LoadChart, PluginList } from '.'
import { useStatus, BotTable, GroupChart, HourChart, LoadChart, PluginList } from '.'
const status = useStatus()
Expand Down
3 changes: 2 additions & 1 deletion packages/plugin-status/client/components/bot-table.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<el-card class="bot-table frameless" header="账号数据" shadow="hover">
<table>
<table v-if="status.bots.length">
<tr>
<th>账号信息</th>
<th>当前消息频率</th>
Expand All @@ -12,6 +12,7 @@
<td>发送 {{ bot.recentRate[0] }}/min,接收 {{ bot.recentRate[1] }}/min</td>
</tr>
</table>
<p v-else>暂无数据。</p>
</el-card>
</template>

Expand Down
42 changes: 42 additions & 0 deletions packages/plugin-status/client/components/group-chart.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<template>
<el-card class="frameless" header="各群发言数量" shadow="hover">
<v-chart v-if="status.groups.length" :option="option" autoresize/>
<p v-else>暂无数据。</p>
</el-card>
</template>

<script lang="ts" setup>
import type { Payload } from '~/server'
import { defineProps, computed } from 'vue'
import { use } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'
import { GridComponent, TooltipComponent } from 'echarts/components'
import { PieChart } from 'echarts/charts'
import VChart from 'vue-echarts'
use([CanvasRenderer, GridComponent, TooltipComponent, PieChart])
const props = defineProps<{ status: Payload }>()
const option = computed(() => ({
tooltip: {
trigger: 'item',
formatter({ data, value }) {
const output = [data.name]
if (data.memberCount) output.push(`人数:${data.memberCount}`)
if (data.assignee) output.push(`接入:${data.assignee}`)
output.push(`日均发言:${+value.toFixed(1)}`)
output.push(`昨日发言:${+data.last.toFixed(1)}`)
return output.join('<br>')
},
},
series: [{
type: 'pie',
data: props.status.groups.sort((a, b) => b.value - a.value),
radius: ['35%', '65%'],
minShowLabelAngle: 3,
}],
}))
</script>
9 changes: 8 additions & 1 deletion packages/plugin-status/client/components/hour-chart.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@
import type { Payload } from '~/server'
import { defineProps, computed } from 'vue'
import { use } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'
import { GridComponent, TooltipComponent } from 'echarts/components'
import { BarChart } from 'echarts/charts'
import VChart from 'vue-echarts'
use([CanvasRenderer, GridComponent, TooltipComponent, BarChart])
const formatHour = (value: number) => `${(value - 0.5).toFixed()}:00-${(value + 0.5).toFixed()}:00`
Expand All @@ -19,7 +26,7 @@ const option = computed(() => ({
axisPointer: {
type: 'cross',
},
formatter (params) {
formatter(params) {
const [{ data: [x], dataIndex, color }] = params
const source = props.status.hours[dataIndex]
const output = [
Expand Down
4 changes: 4 additions & 0 deletions packages/plugin-status/client/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ $warning: #E6A23C;

.frameless > & .el-card__body {
padding: 0;

p {
margin: 1.5rem 2rem;
}
}
}

Expand Down
2 changes: 2 additions & 0 deletions packages/plugin-status/client/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { ref, onMounted } from 'vue'
import type { Payload } from '~/server'
import BotTable from './components/bot-table.vue'
import GroupChart from './components/group-chart.vue'
import HourChart from './components/hour-chart.vue'
import LoadChart from './components/load-chart.vue'
import PluginList from './components/plugin-list.vue'

export {
BotTable,
GroupChart,
HourChart,
LoadChart,
PluginList,
Expand Down
13 changes: 1 addition & 12 deletions packages/plugin-status/client/main.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
import { createApp } from 'vue'
import { ElCard, ElCollapseTransition } from 'element-plus'
import { use } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'
import { GridComponent, TooltipComponent } from 'echarts/components'
import { BarChart } from 'echarts/charts'
import VChart, { THEME_KEY } from 'vue-echarts'
import { THEME_KEY } from 'vue-echarts'
import Layout from '~/layout'

// for el-collapse-transition
Expand All @@ -14,18 +10,11 @@ import 'element-plus/lib/theme-chalk/el-card.css'

import './index.scss'

use(CanvasRenderer)
use(BarChart)
use(GridComponent)
use(TooltipComponent)

const app = createApp(Layout)

app.provide(THEME_KEY, 'light')

app.use(ElCard)
app.use(ElCollapseTransition)

app.component('v-chart', VChart)

app.mount('#app')
2 changes: 2 additions & 0 deletions packages/plugin-status/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { interpolate, Time } from 'koishi-utils'
import { ActiveData } from './database'
import * as WebUI from './webui'
import Profile from './profile'
import Statistics from './stats'

export * from './database'

Expand Down Expand Up @@ -102,5 +103,6 @@ export function apply(ctx: Context, config: Config = {}) {
}

ctx.plugin(Profile)
ctx.plugin(Statistics)
if (config.port) ctx.plugin(WebUI, config)
}
24 changes: 13 additions & 11 deletions packages/plugin-status/server/stats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {} from 'koishi-plugin-teach'
import MysqlDatabase from 'koishi-plugin-mysql'
import Profile from './profile'

const logger = new Logger('stats')
const logger = new Logger('status')

type Activity = Record<number, number>
type StatRecord = Record<string, number>
Expand Down Expand Up @@ -96,7 +96,7 @@ namespace Stat {
const entries = Object.entries(value)
if (!entries.length) return
return `\`${name}\` = JSON_SET(\`${name}\`, ${entries.map(([key, value]) => {
return `'$."${key}"', IFNULL(\`${name}\`->'$."${key}"', 0) + ${value}`
return `'$."${key}"', IFNULL(JSON_EXTRACT(\`${name}\`, '$."${key}"'), 0) + ${value}`
}).join(', ')})`
},
})
Expand Down Expand Up @@ -137,7 +137,7 @@ namespace Stat {
const daily = new Stat.Recorded('stats_daily', dailyFields)
const hourly = new Stat.Numerical('stats_hourly', hourlyFields)
const longterm = new Stat.Numerical('stats_longterm', longtermFields)
const groups: Record<number, number> = {}
const groups: Record<string, number> = {}

let lastUpdate = new Date()
let updateHour = lastUpdate.getHours()
Expand All @@ -161,8 +161,8 @@ async function updateStats(db: MysqlDatabase, forced = false) {
for (const id in groups) {
sqls.push(`
UPDATE \`channel\` SET
\`activity\` = JSON_SET(\`activity\`, '$."${updateNumber}"', IFNULL(\`activity\`->'$."${updateNumber}"', 0) + ${groups[id]})
WHERE \`id\` = ${id}
\`activity\` = JSON_SET(\`activity\`, '$."${updateNumber}"', IFNULL(JSON_EXTRACT(\`activity\`, '$."${updateNumber}"'), 0) + ${groups[id]})
WHERE \`id\` = '${id}'
`)
delete groups[id]
}
Expand Down Expand Up @@ -335,7 +335,8 @@ namespace Statistics {
const botSend = average(historyDaily.map(stat => stat.botSend))
const botReceive = average(historyDaily.map(stat => stat.botReceive))
profile.bots.forEach((bot) => {
bot.recentRate = [botSend[bot.selfId] || 0, botReceive[bot.selfId] || 0]
const sid = `${bot.platform}:${bot.selfId}`
bot.recentRate = [botSend[sid] || 0, botReceive[sid] || 0]
})
}

Expand All @@ -351,8 +352,9 @@ namespace Statistics {
process.on('SIGINT', handleSigInt)
})

ctx.before('disconnect', () => {
ctx.before('disconnect', async () => {
process.off('SIGINT', handleSigInt)
await updateStats(db, true)
})

ctx.before('command', ({ command, session }) => {
Expand All @@ -374,16 +376,16 @@ namespace Statistics {
hourly.data.total += 1
hourly.data[session.subtype] += 1
longterm.data.message += 1
daily.add('botSend', session.selfId)
daily.add('botSend', session.sid)
if (session.subtype === 'group') {
daily.add('group', session.groupId)
groups[session.groupId] = (groups[session.groupId] || 0) + 1
daily.add('group', session.gid)
groups[session.gid] = (groups[session.gid] || 0) + 1
}
updateStats(db)
}

ctx.on('message', (session) => {
daily.add('botReceive', session.selfId)
daily.add('botReceive', session.sid)
})

ctx.on('before-send', (session) => {
Expand Down

0 comments on commit cbe38c3

Please sign in to comment.