137 lines
3.2 KiB
Vue
137 lines
3.2 KiB
Vue
<template>
|
|
<div>
|
|
<div class="controls">
|
|
<h4>扫码统计</h4>
|
|
<CButtonGroup class="mode-buttons" role="group" aria-label="Basic example">
|
|
<CButton @click="visible_mode=k" v-for="(m, k) in modes" :key="k" :color="k == visible_mode ? 'primary' : 'secondary'">{{ m.name }}</CButton>
|
|
</CButtonGroup>
|
|
</div>
|
|
<div class="chart" v-for="(m, k) in modes" v-show="k == visible_mode" :key="k">
|
|
<CChart v-if="data[k]" type="bar" :data="data[k]" />
|
|
<div v-else class="loading">
|
|
<CSpinner variant="grow"/>
|
|
<div>
|
|
正在加载
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { CChart } from '@coreui/vue-chartjs'
|
|
export default {
|
|
name: 'Chart',
|
|
props: [],
|
|
components: {
|
|
CChart,
|
|
},
|
|
data: function () {
|
|
return {
|
|
data: {},
|
|
modes: {
|
|
hour: {
|
|
name: '最近1小时',
|
|
unit: 'minute',
|
|
hours: 1,
|
|
},
|
|
day: {
|
|
name: '过去24小时',
|
|
unit: 'hour',
|
|
hours: 24,
|
|
},
|
|
week: {
|
|
name: '最近7天',
|
|
unit: 'day',
|
|
hours: 24 * 7,
|
|
},
|
|
month: {
|
|
name: '过去30天 ',
|
|
unit: 'day',
|
|
hours: 24 * 30,
|
|
},
|
|
},
|
|
visible_mode: 'day',
|
|
};
|
|
},
|
|
computed: {
|
|
},
|
|
methods: {
|
|
load_data: async function(mode_name) {
|
|
var mode = this.modes[mode_name];
|
|
var unit = mode.unit;
|
|
var until = Math.floor(Date.now() / 1000);
|
|
var seconds = 3600 * mode.hours;
|
|
var since = until - seconds;
|
|
var r = await this.$root.api_get('/api/v1/counter-history/?name=qr-verify-ok&since=' + since +
|
|
'&until=' + until + '&unit=' + unit);
|
|
var ok_data = r.data.data;
|
|
r = await this.$root.api_get('/api/v1/counter-history/?name=qr-verify-fail&since=' + since +
|
|
'&until=' + until + '&unit=' + unit);
|
|
var fail_data = r.data.data;
|
|
const labels = ok_data.map(x => this.format_timestamp(x[0], unit == 'day'));
|
|
|
|
if (ok_data.length != fail_data.length) return;
|
|
|
|
for (var i = 0; i < ok_data.length; i++) {
|
|
if (ok_data[i][0] != fail_data[i][0]) return;
|
|
}
|
|
|
|
var data = {
|
|
labels: labels,
|
|
datasets: [
|
|
{
|
|
label: '验证成功',
|
|
backgroundColor: '#00aa00',
|
|
data: ok_data.map(x => x[1]),
|
|
},
|
|
{
|
|
label: '验证失败',
|
|
backgroundColor: '#888888',
|
|
data: fail_data.map(x => x[1]),
|
|
},
|
|
],
|
|
};
|
|
this.data[mode_name] = data;
|
|
},
|
|
reload: function() {
|
|
this.data = {};
|
|
for (var mn in this.modes) {
|
|
this.load_data(mn);
|
|
}
|
|
this.load_by_province();
|
|
},
|
|
async load_by_province() {
|
|
var r = await this.$root.api_get("/api/v1/scan-stats-by-province/?hours=24");
|
|
console.log(r.data);
|
|
},
|
|
},
|
|
mounted() {
|
|
this.reload();
|
|
},
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
div.controls {
|
|
text-align: center;
|
|
}
|
|
h4 {
|
|
margin: 3rem 0 0 0;
|
|
}
|
|
div.chart {
|
|
margin: 1rem 0;
|
|
border: 1px solid #888;
|
|
padding: 1rem;
|
|
}
|
|
|
|
.mode-buttons {
|
|
margin: 2rem 0;
|
|
}
|
|
div.loading {
|
|
text-align: center;
|
|
margin: 2rem 0 2rem;
|
|
}
|
|
</style>
|
|
|