mirror of https://github.com/openspug/spug
A 发布申请TOP5图表支持选择时间范围统计
parent
9dd1ee8ae6
commit
6c91f6f5f2
|
@ -8,7 +8,8 @@ from apps.schedule.models import Task
|
||||||
from apps.monitor.models import Detection
|
from apps.monitor.models import Detection
|
||||||
from apps.alarm.models import Alarm
|
from apps.alarm.models import Alarm
|
||||||
from apps.deploy.models import Deploy, DeployRequest
|
from apps.deploy.models import Deploy, DeployRequest
|
||||||
from libs.utils import json_response, human_date
|
from libs.utils import json_response, human_date, parse_time
|
||||||
|
from libs.parser import JsonParser, Argument
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
@ -35,11 +36,18 @@ def get_alarm(request):
|
||||||
|
|
||||||
|
|
||||||
def get_request(request):
|
def get_request(request):
|
||||||
|
form, error = JsonParser(
|
||||||
|
Argument('duration', type=list, help='参数错误')
|
||||||
|
).parse(request.body)
|
||||||
|
if error is None:
|
||||||
|
s_date = form.duration[0]
|
||||||
|
e_date = (parse_time(form.duration[1]) + timedelta(days=1)).strftime('%Y-%m-%d')
|
||||||
data = {x.id: {'name': x.name, 'count': 0} for x in App.objects.all()}
|
data = {x.id: {'name': x.name, 'count': 0} for x in App.objects.all()}
|
||||||
for req in DeployRequest.objects.filter(created_at__gt=human_date()):
|
for req in DeployRequest.objects.filter(created_at__gt=s_date, created_at__lt=e_date):
|
||||||
data[req.deploy.app_id]['count'] += 1
|
data[req.deploy.app_id]['count'] += 1
|
||||||
data = sorted(data.values(), key=lambda x: x['count'], reverse=True)[:5]
|
data = sorted(data.values(), key=lambda x: x['count'], reverse=True)[:5]
|
||||||
return json_response(data)
|
return json_response(data)
|
||||||
|
return json_response(error=error)
|
||||||
|
|
||||||
|
|
||||||
def get_deploy(request):
|
def get_deploy(request):
|
||||||
|
|
|
@ -3,30 +3,64 @@
|
||||||
* Copyright (c) <spug.dev@gmail.com>
|
* Copyright (c) <spug.dev@gmail.com>
|
||||||
* Released under the AGPL-3.0 License.
|
* Released under the AGPL-3.0 License.
|
||||||
*/
|
*/
|
||||||
import React from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { Card } from 'antd';
|
import { Card, DatePicker } from 'antd';
|
||||||
import { Chart, Geom, Axis, Tooltip } from 'bizcharts';
|
import { Chart, Geom, Axis, Tooltip } from 'bizcharts';
|
||||||
|
import styles from './index.module.css';
|
||||||
|
import moment from 'moment';
|
||||||
import { http } from 'libs';
|
import { http } from 'libs';
|
||||||
|
|
||||||
export default class RequestTop extends React.Component {
|
|
||||||
constructor(props) {
|
export default function () {
|
||||||
super(props);
|
const [loading, setLoading] = useState(false);
|
||||||
this.state = {
|
const [duration, setDuration] = useState([moment(), moment()]);
|
||||||
loading: true,
|
const [range, setRange] = useState('day');
|
||||||
res: []
|
const [res, setRes] = useState([])
|
||||||
};
|
|
||||||
|
useEffect(() => {
|
||||||
|
setLoading(true);
|
||||||
|
const strDuration = duration.map(x => x.format('YYYY-MM-DD'))
|
||||||
|
http.post('/api/home/request/', {duration: strDuration})
|
||||||
|
.then(res => setRes(res))
|
||||||
|
.finally(() => setLoading(false))
|
||||||
|
}, [duration])
|
||||||
|
|
||||||
|
function handleClick(val) {
|
||||||
|
let duration = [];
|
||||||
|
switch (val) {
|
||||||
|
case 'day':
|
||||||
|
setRange('day');
|
||||||
|
duration = [moment(), moment()];
|
||||||
|
break;
|
||||||
|
case 'week':
|
||||||
|
setRange('week');
|
||||||
|
duration = [moment().weekday(0), moment().weekday(6)];
|
||||||
|
break;
|
||||||
|
case 'month':
|
||||||
|
setRange('month');
|
||||||
|
const s_date = moment().startOf('month')
|
||||||
|
const e_date = moment().endOf('month')
|
||||||
|
duration = [s_date, e_date];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
setRange('custom')
|
||||||
|
duration = val
|
||||||
|
}
|
||||||
|
setDuration(duration)
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
http.get('/api/home/request/')
|
|
||||||
.then(res => this.setState({res}))
|
|
||||||
.finally(() => this.setState({loading: false}))
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const {res, loading} = this.state;
|
|
||||||
return (
|
return (
|
||||||
<Card loading={loading} title="发布申请Top5">
|
<Card loading={loading} title="发布申请Top5" extra={(
|
||||||
|
<div style={{display: 'flex', alignItems: 'center'}}>
|
||||||
|
<span className={range === 'day' ? styles.spanButtonActive : styles.spanButton}
|
||||||
|
onClick={() => handleClick('day')}>今日</span>
|
||||||
|
<span className={range === 'week' ? styles.spanButtonActive : styles.spanButton}
|
||||||
|
onClick={() => handleClick('week')}>本周</span>
|
||||||
|
<span className={range === 'month' ? styles.spanButtonActive : styles.spanButton}
|
||||||
|
onClick={() => handleClick('month')}>本月</span>
|
||||||
|
<DatePicker.RangePicker value={duration} onChange={handleClick}/>
|
||||||
|
</div>
|
||||||
|
)}>
|
||||||
<Chart height={300} data={res} padding={[10, 0, 30, 35]} forceFit>
|
<Chart height={300} data={res} padding={[10, 0, 30, 35]} forceFit>
|
||||||
<Axis name="name"/>
|
<Axis name="name"/>
|
||||||
<Axis name="count" title/>
|
<Axis name="count" title/>
|
||||||
|
@ -35,5 +69,4 @@ export default class RequestTop extends React.Component {
|
||||||
</Chart>
|
</Chart>
|
||||||
</Card>
|
</Card>
|
||||||
)
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
:global(.ant-card-extra) {
|
||||||
|
padding: 12px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spanButton {
|
||||||
|
cursor: pointer;
|
||||||
|
margin-right: 24px;
|
||||||
|
color: rgba(0, 0, 0, .65);
|
||||||
|
}
|
||||||
|
|
||||||
|
.spanButtonActive {
|
||||||
|
cursor: pointer;
|
||||||
|
margin-right: 24px;
|
||||||
|
color: #1890ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spanButton:hover {
|
||||||
|
color: #1890ff;
|
||||||
|
}
|
Loading…
Reference in New Issue