update SearchMonitor
This commit is contained in:
parent
c45f58e49a
commit
688005a8a7
|
@ -42,6 +42,16 @@ export default [
|
|||
name: 'search',
|
||||
component: './Dashboard/SearchMonitor',
|
||||
},
|
||||
// {
|
||||
// path: '/platform/analysis',
|
||||
// name: 'analysis',
|
||||
// component: './Dashboard/Analysis',
|
||||
// },
|
||||
// {
|
||||
// path: '/platform/monitor',
|
||||
// name: 'monitor',
|
||||
// component: './Dashboard/Monitor',
|
||||
// },
|
||||
]
|
||||
},
|
||||
|
||||
|
|
|
@ -38,6 +38,132 @@ for (let i = 0; i < 50; i += 1) {
|
|||
status: Math.floor((Math.random() * 10) % 2),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
const searchDataBaseTerms = [{
|
||||
"name": "北京",
|
||||
"value": Math.floor((Math.random() * 1000)),
|
||||
"category": "城市"
|
||||
}, {
|
||||
"name": "广州",
|
||||
"value": Math.floor((Math.random() * 1000)),
|
||||
"category": "城市"
|
||||
}, {
|
||||
"name": "深圳",
|
||||
"value": Math.floor((Math.random() * 1000)),
|
||||
"category": "城市"
|
||||
}, {
|
||||
"name": "长沙",
|
||||
"value": Math.floor((Math.random() * 1000)),
|
||||
"category": "城市"
|
||||
}, {
|
||||
"name": "上海",
|
||||
"value": Math.floor((Math.random() * 1000)),
|
||||
"category": "城市"
|
||||
}, {
|
||||
"name": "成都",
|
||||
"value": Math.floor((Math.random() * 1000)),
|
||||
"category": "城市"
|
||||
}, {
|
||||
"name": "哈尔滨",
|
||||
"value": Math.floor((Math.random() * 1000)),
|
||||
"category": "城市"
|
||||
}, {
|
||||
"name": "海口",
|
||||
"value": Math.floor((Math.random() * 1000)),
|
||||
"category": "城市"
|
||||
}, {
|
||||
"name": "青岛",
|
||||
"value": Math.floor((Math.random() * 1000)),
|
||||
"category": "城市"
|
||||
}, {
|
||||
"name": "G71",
|
||||
"value": Math.floor((Math.random() * 1000)),
|
||||
"category": "车次"
|
||||
}, {
|
||||
"name": "G121",
|
||||
"value": Math.floor((Math.random() * 1000)),
|
||||
"category": "车次"
|
||||
}, {
|
||||
"name": "T109",
|
||||
"value": Math.floor((Math.random() * 1000)),
|
||||
"category": "车次"
|
||||
}, {
|
||||
"name": "K81",
|
||||
"value": Math.floor((Math.random() * 1000)),
|
||||
"category": "车次"
|
||||
}, {
|
||||
"name": "Z13",
|
||||
"value": Math.floor((Math.random() * 1000)),
|
||||
"category": "车次"
|
||||
}, {
|
||||
"name": "Z121",
|
||||
"value": Math.floor((Math.random() * 1000)),
|
||||
"category": "车次"
|
||||
}, {
|
||||
"name": "G431",
|
||||
"value": Math.floor((Math.random() * 1000)),
|
||||
"category": "车次"
|
||||
}, {
|
||||
"name": "退票",
|
||||
"value": Math.floor((Math.random() * 1000)),
|
||||
"category": "票务"
|
||||
}, {
|
||||
"name": "春运",
|
||||
"value": Math.floor((Math.random() * 1000)),
|
||||
"category": "票务"
|
||||
}, {
|
||||
"name": "学生票",
|
||||
"value": Math.floor((Math.random() * 1000)),
|
||||
"category": "票务"
|
||||
}, {
|
||||
"name": "二等座",
|
||||
"value": Math.floor((Math.random() * 1000)),
|
||||
"category": "其他"
|
||||
}, {
|
||||
"name": "订餐",
|
||||
"value": Math.floor((Math.random() * 1000)),
|
||||
"category": "其他"
|
||||
}];
|
||||
|
||||
const searchDataInfini = [];
|
||||
for (let i = 0; i < searchDataBaseTerms.length; i += 1) {
|
||||
searchDataInfini.push({
|
||||
index: i + 1,
|
||||
keyword: `${searchDataBaseTerms[i].name}`,
|
||||
count: Math.floor(Math.random() * 1000),
|
||||
range: Math.floor(Math.random() * 100),
|
||||
status: Math.floor((Math.random() * 10) % 2),
|
||||
});
|
||||
}
|
||||
|
||||
const docTypeDataInfini = [
|
||||
{
|
||||
x: 'user',
|
||||
y: 39274,
|
||||
},
|
||||
{
|
||||
x: 'city',
|
||||
y: 31008,
|
||||
},
|
||||
{
|
||||
x: 'train',
|
||||
y: 27610,
|
||||
},
|
||||
{
|
||||
x: 'news',
|
||||
y: 19302,
|
||||
},
|
||||
{
|
||||
x: 'order',
|
||||
y: 17624,
|
||||
},
|
||||
{
|
||||
x: 'other',
|
||||
y: 12900,
|
||||
},
|
||||
];
|
||||
|
||||
const salesTypeData = [
|
||||
{
|
||||
x: '家用电器',
|
||||
|
@ -189,6 +315,8 @@ const getFakeChartData = {
|
|||
salesTypeDataOnline,
|
||||
salesTypeDataOffline,
|
||||
radarData,
|
||||
searchDataInfini,
|
||||
docTypeDataInfini,
|
||||
};
|
||||
|
||||
export default {
|
||||
|
|
|
@ -112,7 +112,7 @@ class GatewayMonitor extends PureComponent {
|
|||
bodyStyle={{ padding: '30px 0 10px' }}
|
||||
style={{ marginTop: 32 }}
|
||||
>
|
||||
<Chart height={400} data={chartDataIndex} scale={cols} forceFit>
|
||||
<Chart height={300} data={chartDataIndex} scale={cols} forceFit>
|
||||
<h3 className='main-title' style={styles.mainTitle}>
|
||||
索引QPS
|
||||
</h3>
|
||||
|
@ -146,7 +146,7 @@ class GatewayMonitor extends PureComponent {
|
|||
style={{ marginTop: 32 }}
|
||||
>
|
||||
<div style={{ padding: '0 24px' }}>
|
||||
<Chart height={400} data={chartDataQuery} scale={cols} forceFit>
|
||||
<Chart height={300} data={chartDataQuery} scale={cols} forceFit>
|
||||
<h3 className='main-title' style={styles.mainTitle}>
|
||||
查询QPS
|
||||
</h3>
|
||||
|
@ -183,7 +183,7 @@ class GatewayMonitor extends PureComponent {
|
|||
bodyStyle={{ padding: '30px 0 10px' }}
|
||||
style={{ marginTop: 32 }}
|
||||
>
|
||||
<Chart height={400} data={chartDataGateway} scale={cols} forceFit>
|
||||
<Chart height={300} data={chartDataGateway} scale={cols} forceFit>
|
||||
<h3 className='main-title' style={styles.mainTitle}>
|
||||
网关写入QPS
|
||||
</h3>
|
||||
|
@ -217,7 +217,7 @@ class GatewayMonitor extends PureComponent {
|
|||
style={{ marginTop: 32 }}
|
||||
>
|
||||
<div style={{ padding: '0 24px' }}>
|
||||
<Chart height={400} data={chartDataTop} scale={cols} forceFit>
|
||||
<Chart height={300} data={chartDataTop} scale={cols} forceFit>
|
||||
<h3 className='main-title' style={styles.mainTitle}>
|
||||
Top用户统计
|
||||
</h3>
|
||||
|
|
|
@ -143,7 +143,7 @@ class TagCloud extends PureComponent {
|
|||
dv.transform({
|
||||
type: "tag-cloud",
|
||||
fields: ["name", "value"],
|
||||
size: [300, 200],
|
||||
size: [400, 300],
|
||||
font: "Verdana",
|
||||
padding: 0,
|
||||
timeInterval: 5000,// max execute time
|
||||
|
@ -176,7 +176,7 @@ class TagCloud extends PureComponent {
|
|||
<Chart
|
||||
// height={window.innerHeight}
|
||||
width={window.innerWidth}
|
||||
height={200}
|
||||
height={248}
|
||||
data={dv}
|
||||
scale={scale}
|
||||
padding={0}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import React, { PureComponent } from 'react';
|
||||
|
||||
import GridContent from '@/components/PageHeaderWrapper/GridContent';
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'dva';
|
||||
import { formatMessage, FormattedMessage } from 'umi/locale';
|
||||
import numeral from 'numeral';
|
||||
import {
|
||||
Row,
|
||||
Col,
|
||||
|
@ -10,16 +11,32 @@ import {
|
|||
Table,
|
||||
Radio,
|
||||
DatePicker,
|
||||
Tooltip,
|
||||
Menu,
|
||||
Dropdown,
|
||||
} from 'antd';
|
||||
import NumberInfo from '@/components/NumberInfo';
|
||||
import {
|
||||
ChartCard,
|
||||
MiniArea,
|
||||
MiniBar,
|
||||
MiniProgress,
|
||||
Field,
|
||||
Bar,
|
||||
Pie,
|
||||
TimelineChart,
|
||||
} from '@/components/Charts';
|
||||
import Trend from '@/components/Trend';
|
||||
import GridContent from '@/components/PageHeaderWrapper/GridContent';
|
||||
import Yuan from '@/utils/Yuan';
|
||||
import { getTimeDistance } from '@/utils/utils';
|
||||
|
||||
import _ from 'lodash';
|
||||
import {
|
||||
G2,
|
||||
Chart,
|
||||
Geom,
|
||||
Axis,
|
||||
Tooltip,
|
||||
Coord,
|
||||
Label,
|
||||
Legend,
|
||||
|
@ -34,17 +51,333 @@ import Slider from 'bizcharts-plugin-slider';
|
|||
import UserStat from './Search/UserStat';
|
||||
import TagCloud from './Search/TagCloud';
|
||||
|
||||
import styles from "./Monitor.less";
|
||||
import styles from './Analysis.less';
|
||||
|
||||
const { TabPane } = Tabs;
|
||||
const { RangePicker } = DatePicker;
|
||||
|
||||
class SearchMonitor extends PureComponent {
|
||||
const rankingListData = [];
|
||||
for (let i = 0; i < 7; i += 1) {
|
||||
rankingListData.push({
|
||||
title: `工专路 ${i} 号店`,
|
||||
total: 323234,
|
||||
});
|
||||
}
|
||||
|
||||
@connect(({ chart, loading }) => ({
|
||||
chart,
|
||||
loading: loading.effects['chart/fetch'],
|
||||
}))
|
||||
class SearchMonitor extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.rankingListData = [];
|
||||
for (let i = 0; i < 7; i += 1) {
|
||||
this.rankingListData.push({
|
||||
title: formatMessage({ id: 'app.analysis.test' }, { no: i }),
|
||||
total: 323234,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
state = {
|
||||
salesType: 'all',
|
||||
currentTabKey: '',
|
||||
rangePickerValue: getTimeDistance('year'),
|
||||
loading: true,
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
const { dispatch } = this.props;
|
||||
this.reqRef = requestAnimationFrame(() => {
|
||||
dispatch({
|
||||
type: 'chart/fetch',
|
||||
});
|
||||
this.timeoutId = setTimeout(() => {
|
||||
this.setState({
|
||||
loading: false,
|
||||
});
|
||||
}, 600);
|
||||
});
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
const { dispatch } = this.props;
|
||||
dispatch({
|
||||
type: 'chart/clear',
|
||||
});
|
||||
cancelAnimationFrame(this.reqRef);
|
||||
clearTimeout(this.timeoutId);
|
||||
}
|
||||
|
||||
handleChangeSalesType = e => {
|
||||
this.setState({
|
||||
salesType: e.target.value,
|
||||
});
|
||||
};
|
||||
|
||||
handleTabChange = key => {
|
||||
this.setState({
|
||||
currentTabKey: key,
|
||||
});
|
||||
};
|
||||
|
||||
handleRangePickerChange = rangePickerValue => {
|
||||
const { dispatch } = this.props;
|
||||
this.setState({
|
||||
rangePickerValue,
|
||||
});
|
||||
|
||||
dispatch({
|
||||
type: 'chart/fetchSalesData',
|
||||
});
|
||||
};
|
||||
|
||||
selectDate = type => {
|
||||
const { dispatch } = this.props;
|
||||
this.setState({
|
||||
rangePickerValue: getTimeDistance(type),
|
||||
});
|
||||
|
||||
dispatch({
|
||||
type: 'chart/fetchSalesData',
|
||||
});
|
||||
};
|
||||
|
||||
isActive(type) {
|
||||
const { rangePickerValue } = this.state;
|
||||
const value = getTimeDistance(type);
|
||||
if (!rangePickerValue[0] || !rangePickerValue[1]) {
|
||||
return '';
|
||||
}
|
||||
if (
|
||||
rangePickerValue[0].isSame(value[0], 'day') &&
|
||||
rangePickerValue[1].isSame(value[1], 'day')
|
||||
) {
|
||||
return styles.currentDate;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
render() {
|
||||
const { rangePickerValue, salesType, loading: propsLoding, currentTabKey } = this.state;
|
||||
const { chart, loading: stateLoading } = this.props;
|
||||
const {
|
||||
visitData,
|
||||
visitData2,
|
||||
salesData,
|
||||
searchData,
|
||||
searchDataInfini,
|
||||
offlineData,
|
||||
offlineChartData,
|
||||
salesTypeData,
|
||||
docTypeDataInfini,
|
||||
salesTypeDataOnline,
|
||||
salesTypeDataOffline,
|
||||
} = chart;
|
||||
const loading = propsLoding || stateLoading;
|
||||
let salesPieData = docTypeDataInfini;
|
||||
|
||||
const menu = (
|
||||
<Menu>
|
||||
<Menu.Item>操作一</Menu.Item>
|
||||
<Menu.Item>操作二</Menu.Item>
|
||||
</Menu>
|
||||
);
|
||||
|
||||
const iconGroup = (
|
||||
<span className={styles.iconGroup}>
|
||||
<Dropdown overlay={menu} placement="bottomRight">
|
||||
<Icon type="ellipsis" />
|
||||
</Dropdown>
|
||||
</span>
|
||||
);
|
||||
|
||||
const salesExtra = (
|
||||
<div className={styles.salesExtraWrap}>
|
||||
<div className={styles.salesExtra}>
|
||||
<a className={this.isActive('today')} onClick={() => this.selectDate('today')}>
|
||||
<FormattedMessage id="app.analysis.all-day" defaultMessage="All Day" />
|
||||
</a>
|
||||
<a className={this.isActive('week')} onClick={() => this.selectDate('week')}>
|
||||
<FormattedMessage id="app.analysis.all-week" defaultMessage="All Week" />
|
||||
</a>
|
||||
<a className={this.isActive('month')} onClick={() => this.selectDate('month')}>
|
||||
<FormattedMessage id="app.analysis.all-month" defaultMessage="All Month" />
|
||||
</a>
|
||||
<a className={this.isActive('year')} onClick={() => this.selectDate('year')}>
|
||||
<FormattedMessage id="app.analysis.all-year" defaultMessage="All Year" />
|
||||
</a>
|
||||
</div>
|
||||
<RangePicker
|
||||
value={rangePickerValue}
|
||||
onChange={this.handleRangePickerChange}
|
||||
style={{ width: 256 }}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: <FormattedMessage id="app.analysis.table.rank" defaultMessage="Rank" />,
|
||||
dataIndex: 'index',
|
||||
key: 'index',
|
||||
},
|
||||
{
|
||||
title: (
|
||||
<FormattedMessage
|
||||
id="app.analysis.table.search-keyword"
|
||||
defaultMessage="Search keyword"
|
||||
/>
|
||||
),
|
||||
dataIndex: 'keyword',
|
||||
key: 'keyword',
|
||||
render: text => <a href="/">{text}</a>,
|
||||
},
|
||||
{
|
||||
title: <FormattedMessage id="app.analysis.table.users" defaultMessage="Users" />,
|
||||
dataIndex: 'count',
|
||||
key: 'count',
|
||||
sorter: (a, b) => a.count - b.count,
|
||||
className: styles.alignRight,
|
||||
},
|
||||
{
|
||||
title: (
|
||||
<FormattedMessage id="app.analysis.table.weekly-range" defaultMessage="Weekly Range" />
|
||||
),
|
||||
dataIndex: 'range',
|
||||
key: 'range',
|
||||
sorter: (a, b) => a.range - b.range,
|
||||
render: (text, record) => (
|
||||
<Trend flag={record.status === 1 ? 'down' : 'up'}>
|
||||
<span style={{ marginRight: 4 }}>{text}%</span>
|
||||
</Trend>
|
||||
),
|
||||
align: 'right',
|
||||
},
|
||||
];
|
||||
|
||||
const activeKey = currentTabKey || (offlineData[0] && offlineData[0].name);
|
||||
|
||||
const CustomTab = ({ data, currentTabKey: currentKey }) => (
|
||||
<Row gutter={8} style={{ width: 138, margin: '8px 0' }}>
|
||||
<Col span={12}>
|
||||
<NumberInfo
|
||||
title={data.name}
|
||||
subTitle={
|
||||
<FormattedMessage
|
||||
id="app.analysis.conversion-rate"
|
||||
defaultMessage="Conversion Rate"
|
||||
/>
|
||||
}
|
||||
gap={2}
|
||||
total={`${data.cvr * 100}%`}
|
||||
theme={currentKey !== data.name && 'light'}
|
||||
/>
|
||||
</Col>
|
||||
<Col span={12} style={{ paddingTop: 36 }}>
|
||||
<Pie
|
||||
animate={false}
|
||||
color={currentKey !== data.name && '#BDE4FF'}
|
||||
inner={0.55}
|
||||
tooltip={false}
|
||||
margin={[0, 0, 0, 0]}
|
||||
percent={data.cvr * 100}
|
||||
height={64}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
);
|
||||
|
||||
const topColResponsiveProps = {
|
||||
xs: 24,
|
||||
sm: 12,
|
||||
md: 12,
|
||||
lg: 12,
|
||||
xl: 6,
|
||||
style: { marginBottom: 24 },
|
||||
};
|
||||
|
||||
return (
|
||||
<GridContent>
|
||||
|
||||
<Row gutter={24}>
|
||||
<Col xl={8} lg={12} md={24} sm={24} xs={24}>
|
||||
<Col xl={12} lg={24} md={24} sm={24} xs={24}>
|
||||
<Card
|
||||
loading={loading}
|
||||
bordered={false}
|
||||
title="热词搜索"
|
||||
style={{ marginTop: 0 }}
|
||||
>
|
||||
<Row gutter={68}>
|
||||
<Col sm={12} xs={24} style={{ marginBottom: 24 }}>
|
||||
<NumberInfo
|
||||
subTitle={
|
||||
<span>
|
||||
<FormattedMessage
|
||||
id="app.analysis.search-users"
|
||||
defaultMessage="search users"
|
||||
/>
|
||||
<Tooltip
|
||||
title={
|
||||
<FormattedMessage
|
||||
id="app.analysis.introduce"
|
||||
defaultMessage="introduce"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Icon style={{ marginLeft: 8 }} type="info-circle-o" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
gap={8}
|
||||
total={numeral(8371).format('0,0')}
|
||||
status="up"
|
||||
subTotal={17.1}
|
||||
/>
|
||||
<MiniArea line height={45} data={visitData2} />
|
||||
</Col>
|
||||
<Col sm={12} xs={24} style={{ marginBottom: 24 }}>
|
||||
<NumberInfo
|
||||
subTitle={
|
||||
<span>
|
||||
<FormattedMessage
|
||||
id="app.analysis.per-capita-search"
|
||||
defaultMessage="Per Capita Search"
|
||||
/>
|
||||
<Tooltip
|
||||
title={
|
||||
<FormattedMessage
|
||||
id="app.analysis.introduce"
|
||||
defaultMessage="introduce"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Icon style={{ marginLeft: 8 }} type="info-circle-o" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
total={2.7}
|
||||
status="down"
|
||||
subTotal={26.2}
|
||||
gap={8}
|
||||
/>
|
||||
<MiniArea line height={45} data={visitData2} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Table
|
||||
rowKey={record => record.index}
|
||||
size="small"
|
||||
columns={columns}
|
||||
dataSource={searchDataInfini}
|
||||
pagination={{
|
||||
style: { marginBottom: 0 },
|
||||
pageSize: 5,
|
||||
}}
|
||||
/>
|
||||
</Card>
|
||||
</Col>
|
||||
<Col xl={12} lg={24} md={24} sm={24} xs={24}>
|
||||
<Card
|
||||
title="用户统计"
|
||||
loading={false}
|
||||
|
@ -54,31 +387,53 @@ class SearchMonitor extends PureComponent {
|
|||
<UserStat></UserStat>
|
||||
</Card>
|
||||
</Col>
|
||||
<Col xl={8} lg={12} md={24} sm={24} xs={24}>
|
||||
<Card
|
||||
title="热门搜索"
|
||||
loading={false}
|
||||
bordered={false}
|
||||
bodyStyle={{ overflow: 'hidden' }}
|
||||
>
|
||||
<TagCloud>
|
||||
</Row>
|
||||
<Row gutter={24}>
|
||||
{/*<Col xl={8} lg={12} md={24} sm={24} xs={24}>*/}
|
||||
{/* <Card*/}
|
||||
{/* title="热门搜索"*/}
|
||||
{/* loading={false}*/}
|
||||
{/* bordered={false}*/}
|
||||
{/* bodyStyle={{ overflow: 'hidden' }}*/}
|
||||
{/* >*/}
|
||||
{/* <TagCloud>*/}
|
||||
|
||||
</TagCloud>
|
||||
</Card>
|
||||
</Col>
|
||||
<Col xl={8} lg={12} md={24} sm={24} xs={24}>
|
||||
{/* </TagCloud>*/}
|
||||
{/* </Card>*/}
|
||||
{/*</Col>*/}
|
||||
<Col xl={12} lg={24} md={24} sm={24} xs={24}>
|
||||
<Card
|
||||
title="新词"
|
||||
loading={false}
|
||||
bordered={false}
|
||||
bodyStyle={{ overflow: 'hidden' }}
|
||||
style={{ marginTop: 24 }}
|
||||
>
|
||||
<TagCloud>
|
||||
|
||||
</TagCloud>
|
||||
</Card>
|
||||
</Col>
|
||||
<Col xl={12} lg={24} md={24} sm={24} xs={24}>
|
||||
<Card
|
||||
loading={loading}
|
||||
bordered={false}
|
||||
title="TOP索引占比"
|
||||
style={{ marginTop: 24 }}
|
||||
>
|
||||
<Pie
|
||||
hasLegend
|
||||
subTitle="TOP INDEX"
|
||||
total={() => {salesPieData.reduce((pre, now) => now.y + pre, 0)}}
|
||||
data={salesPieData}
|
||||
valueFormat={value => {value}}
|
||||
height={248}
|
||||
lineWidth={4}
|
||||
/>
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
</GridContent>
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue