|
|
@@ -1,70 +1,28 @@
|
|
|
-import React, { Component } from 'react';
|
|
|
+import React, { Component, Suspense } from 'react';
|
|
|
import { connect } from 'dva';
|
|
|
-import { formatMessage, FormattedMessage } from 'umi/locale';
|
|
|
-import {
|
|
|
- Row,
|
|
|
- Col,
|
|
|
- Icon,
|
|
|
- Card,
|
|
|
- Tabs,
|
|
|
- Table,
|
|
|
- Radio,
|
|
|
- DatePicker,
|
|
|
- Tooltip,
|
|
|
- Menu,
|
|
|
- Dropdown,
|
|
|
-} from 'antd';
|
|
|
-import {
|
|
|
- ChartCard,
|
|
|
- MiniArea,
|
|
|
- MiniBar,
|
|
|
- MiniProgress,
|
|
|
- Field,
|
|
|
- Bar,
|
|
|
- Pie,
|
|
|
- TimelineChart,
|
|
|
-} from '@/components/Charts';
|
|
|
-import Trend from '@/components/Trend';
|
|
|
-import NumberInfo from '@/components/NumberInfo';
|
|
|
-import numeral from 'numeral';
|
|
|
+import { Row, Col, Icon, Menu, Dropdown } from 'antd';
|
|
|
+
|
|
|
import GridContent from '@/components/PageHeaderWrapper/GridContent';
|
|
|
-import Yuan from '@/utils/Yuan';
|
|
|
import { getTimeDistance } from '@/utils/utils';
|
|
|
|
|
|
import styles from './Analysis.less';
|
|
|
+import PageLoading from '@/components/PageLoading';
|
|
|
|
|
|
-const { TabPane } = Tabs;
|
|
|
-const { RangePicker } = DatePicker;
|
|
|
-
|
|
|
-const rankingListData = [];
|
|
|
-for (let i = 0; i < 7; i += 1) {
|
|
|
- rankingListData.push({
|
|
|
- title: `工专路 ${i} 号店`,
|
|
|
- total: 323234,
|
|
|
- });
|
|
|
-}
|
|
|
+const IntroduceRow = React.lazy(() => import('./IntroduceRow'));
|
|
|
+const SalesCard = React.lazy(() => import('./SalesCard'));
|
|
|
+const TopSearch = React.lazy(() => import('./TopSearch'));
|
|
|
+const ProportionSales = React.lazy(() => import('./ProportionSales'));
|
|
|
+const OfflineData = React.lazy(() => import('./OfflineData'));
|
|
|
|
|
|
@connect(({ chart, loading }) => ({
|
|
|
chart,
|
|
|
loading: loading.effects['chart/fetch'],
|
|
|
}))
|
|
|
class Analysis 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() {
|
|
|
@@ -73,11 +31,6 @@ class Analysis extends Component {
|
|
|
dispatch({
|
|
|
type: 'chart/fetch',
|
|
|
});
|
|
|
- this.timeoutId = setTimeout(() => {
|
|
|
- this.setState({
|
|
|
- loading: false,
|
|
|
- });
|
|
|
- }, 600);
|
|
|
});
|
|
|
}
|
|
|
|
|
|
@@ -124,7 +77,7 @@ class Analysis extends Component {
|
|
|
});
|
|
|
};
|
|
|
|
|
|
- isActive(type) {
|
|
|
+ isActive = type => {
|
|
|
const { rangePickerValue } = this.state;
|
|
|
const value = getTimeDistance(type);
|
|
|
if (!rangePickerValue[0] || !rangePickerValue[1]) {
|
|
|
@@ -137,11 +90,11 @@ class Analysis extends Component {
|
|
|
return styles.currentDate;
|
|
|
}
|
|
|
return '';
|
|
|
- }
|
|
|
+ };
|
|
|
|
|
|
render() {
|
|
|
- const { rangePickerValue, salesType, loading: stateLoading, currentTabKey } = this.state;
|
|
|
- const { chart, loading: propsLoading } = this.props;
|
|
|
+ const { rangePickerValue, salesType, currentTabKey } = this.state;
|
|
|
+ const { chart, loading } = this.props;
|
|
|
const {
|
|
|
visitData,
|
|
|
visitData2,
|
|
|
@@ -153,7 +106,6 @@ class Analysis extends Component {
|
|
|
salesTypeDataOnline,
|
|
|
salesTypeDataOffline,
|
|
|
} = chart;
|
|
|
- const loading = propsLoading || stateLoading;
|
|
|
let salesPieData;
|
|
|
if (salesType === 'all') {
|
|
|
salesPieData = salesTypeData;
|
|
|
@@ -167,7 +119,7 @@ class Analysis extends Component {
|
|
|
</Menu>
|
|
|
);
|
|
|
|
|
|
- const iconGroup = (
|
|
|
+ const dropdownGroup = (
|
|
|
<span className={styles.iconGroup}>
|
|
|
<Dropdown overlay={menu} placement="bottomRight">
|
|
|
<Icon type="ellipsis" />
|
|
|
@@ -175,515 +127,56 @@ class Analysis extends Component {
|
|
|
</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 {...topColResponsiveProps}>
|
|
|
- <ChartCard
|
|
|
- bordered={false}
|
|
|
- title={
|
|
|
- <FormattedMessage id="app.analysis.total-sales" defaultMessage="Total Sales" />
|
|
|
- }
|
|
|
- action={
|
|
|
- <Tooltip
|
|
|
- title={
|
|
|
- <FormattedMessage id="app.analysis.introduce" defaultMessage="Introduce" />
|
|
|
- }
|
|
|
- >
|
|
|
- <Icon type="info-circle-o" />
|
|
|
- </Tooltip>
|
|
|
- }
|
|
|
- loading={loading}
|
|
|
- total={() => <Yuan>126560</Yuan>}
|
|
|
- footer={
|
|
|
- <Field
|
|
|
- label={
|
|
|
- <FormattedMessage id="app.analysis.day-sales" defaultMessage="Daily Sales" />
|
|
|
- }
|
|
|
- value={`¥${numeral(12423).format('0,0')}`}
|
|
|
- />
|
|
|
- }
|
|
|
- contentHeight={46}
|
|
|
- >
|
|
|
- <Trend flag="up" style={{ marginRight: 16 }}>
|
|
|
- <FormattedMessage id="app.analysis.week" defaultMessage="Weekly Changes" />
|
|
|
- <span className={styles.trendText}>12%</span>
|
|
|
- </Trend>
|
|
|
- <Trend flag="down">
|
|
|
- <FormattedMessage id="app.analysis.day" defaultMessage="Daily Changes" />
|
|
|
- <span className={styles.trendText}>11%</span>
|
|
|
- </Trend>
|
|
|
- </ChartCard>
|
|
|
- </Col>
|
|
|
-
|
|
|
- <Col {...topColResponsiveProps}>
|
|
|
- <ChartCard
|
|
|
- bordered={false}
|
|
|
- loading={loading}
|
|
|
- title={<FormattedMessage id="app.analysis.visits" defaultMessage="Visits" />}
|
|
|
- action={
|
|
|
- <Tooltip
|
|
|
- title={
|
|
|
- <FormattedMessage id="app.analysis.introduce" defaultMessage="Introduce" />
|
|
|
- }
|
|
|
- >
|
|
|
- <Icon type="info-circle-o" />
|
|
|
- </Tooltip>
|
|
|
- }
|
|
|
- total={numeral(8846).format('0,0')}
|
|
|
- footer={
|
|
|
- <Field
|
|
|
- label={
|
|
|
- <FormattedMessage id="app.analysis.day-visits" defaultMessage="Daily Visits" />
|
|
|
- }
|
|
|
- value={numeral(1234).format('0,0')}
|
|
|
- />
|
|
|
- }
|
|
|
- contentHeight={46}
|
|
|
- >
|
|
|
- <MiniArea color="#975FE4" data={visitData} />
|
|
|
- </ChartCard>
|
|
|
- </Col>
|
|
|
- <Col {...topColResponsiveProps}>
|
|
|
- <ChartCard
|
|
|
- bordered={false}
|
|
|
- loading={loading}
|
|
|
- title={<FormattedMessage id="app.analysis.payments" defaultMessage="Payments" />}
|
|
|
- action={
|
|
|
- <Tooltip
|
|
|
- title={
|
|
|
- <FormattedMessage id="app.analysis.introduce" defaultMessage="Introduce" />
|
|
|
- }
|
|
|
- >
|
|
|
- <Icon type="info-circle-o" />
|
|
|
- </Tooltip>
|
|
|
- }
|
|
|
- total={numeral(6560).format('0,0')}
|
|
|
- footer={
|
|
|
- <Field
|
|
|
- label={
|
|
|
- <FormattedMessage
|
|
|
- id="app.analysis.conversion-rate"
|
|
|
- defaultMessage="Conversion Rate"
|
|
|
- />
|
|
|
- }
|
|
|
- value="60%"
|
|
|
- />
|
|
|
- }
|
|
|
- contentHeight={46}
|
|
|
- >
|
|
|
- <MiniBar data={visitData} />
|
|
|
- </ChartCard>
|
|
|
- </Col>
|
|
|
- <Col {...topColResponsiveProps}>
|
|
|
- <ChartCard
|
|
|
- loading={loading}
|
|
|
- bordered={false}
|
|
|
- title={
|
|
|
- <FormattedMessage
|
|
|
- id="app.analysis.operational-effect"
|
|
|
- defaultMessage="Operational Effect"
|
|
|
- />
|
|
|
- }
|
|
|
- action={
|
|
|
- <Tooltip
|
|
|
- title={
|
|
|
- <FormattedMessage id="app.analysis.introduce" defaultMessage="Introduce" />
|
|
|
- }
|
|
|
- >
|
|
|
- <Icon type="info-circle-o" />
|
|
|
- </Tooltip>
|
|
|
- }
|
|
|
- total="78%"
|
|
|
- footer={
|
|
|
- <div style={{ whiteSpace: 'nowrap', overflow: 'hidden' }}>
|
|
|
- <Trend flag="up" style={{ marginRight: 16 }}>
|
|
|
- <FormattedMessage id="app.analysis.week" defaultMessage="Weekly Changes" />
|
|
|
- <span className={styles.trendText}>12%</span>
|
|
|
- </Trend>
|
|
|
- <Trend flag="down">
|
|
|
- <FormattedMessage id="app.analysis.day" defaultMessage="Weekly Changes" />
|
|
|
- <span className={styles.trendText}>11%</span>
|
|
|
- </Trend>
|
|
|
- </div>
|
|
|
- }
|
|
|
- contentHeight={46}
|
|
|
- >
|
|
|
- <MiniProgress percent={78} strokeWidth={8} target={80} color="#13C2C2" />
|
|
|
- </ChartCard>
|
|
|
- </Col>
|
|
|
- </Row>
|
|
|
-
|
|
|
- <Card loading={loading} bordered={false} bodyStyle={{ padding: 0 }}>
|
|
|
- <div className={styles.salesCard}>
|
|
|
- <Tabs tabBarExtraContent={salesExtra} size="large" tabBarStyle={{ marginBottom: 24 }}>
|
|
|
- <TabPane
|
|
|
- tab={<FormattedMessage id="app.analysis.sales" defaultMessage="Sales" />}
|
|
|
- key="sales"
|
|
|
- >
|
|
|
- <Row>
|
|
|
- <Col xl={16} lg={12} md={12} sm={24} xs={24}>
|
|
|
- <div className={styles.salesBar}>
|
|
|
- <Bar
|
|
|
- height={295}
|
|
|
- title={
|
|
|
- <FormattedMessage
|
|
|
- id="app.analysis.sales-trend"
|
|
|
- defaultMessage="Sales Trend"
|
|
|
- />
|
|
|
- }
|
|
|
- data={salesData}
|
|
|
- />
|
|
|
- </div>
|
|
|
- </Col>
|
|
|
- <Col xl={8} lg={12} md={12} sm={24} xs={24}>
|
|
|
- <div className={styles.salesRank}>
|
|
|
- <h4 className={styles.rankingTitle}>
|
|
|
- <FormattedMessage
|
|
|
- id="app.analysis.sales-ranking"
|
|
|
- defaultMessage="Sales Ranking"
|
|
|
- />
|
|
|
- </h4>
|
|
|
- <ul className={styles.rankingList}>
|
|
|
- {this.rankingListData.map((item, i) => (
|
|
|
- <li key={item.title}>
|
|
|
- <span
|
|
|
- className={`${styles.rankingItemNumber} ${
|
|
|
- i < 3 ? styles.active : ''
|
|
|
- }`}
|
|
|
- >
|
|
|
- {i + 1}
|
|
|
- </span>
|
|
|
- <span className={styles.rankingItemTitle} title={item.title}>
|
|
|
- {item.title}
|
|
|
- </span>
|
|
|
- <span className={styles.rankingItemValue}>
|
|
|
- {numeral(item.total).format('0,0')}
|
|
|
- </span>
|
|
|
- </li>
|
|
|
- ))}
|
|
|
- </ul>
|
|
|
- </div>
|
|
|
- </Col>
|
|
|
- </Row>
|
|
|
- </TabPane>
|
|
|
- <TabPane
|
|
|
- tab={<FormattedMessage id="app.analysis.visits" defaultMessage="Visits" />}
|
|
|
- key="views"
|
|
|
- >
|
|
|
- <Row>
|
|
|
- <Col xl={16} lg={12} md={12} sm={24} xs={24}>
|
|
|
- <div className={styles.salesBar}>
|
|
|
- <Bar
|
|
|
- height={292}
|
|
|
- title={
|
|
|
- <FormattedMessage
|
|
|
- id="app.analysis.visits-trend"
|
|
|
- defaultMessage="Visits Trend"
|
|
|
- />
|
|
|
- }
|
|
|
- data={salesData}
|
|
|
- />
|
|
|
- </div>
|
|
|
- </Col>
|
|
|
- <Col xl={8} lg={12} md={12} sm={24} xs={24}>
|
|
|
- <div className={styles.salesRank}>
|
|
|
- <h4 className={styles.rankingTitle}>
|
|
|
- <FormattedMessage
|
|
|
- id="app.analysis.visits-ranking"
|
|
|
- defaultMessage="Visits Ranking"
|
|
|
- />
|
|
|
- </h4>
|
|
|
- <ul className={styles.rankingList}>
|
|
|
- {this.rankingListData.map((item, i) => (
|
|
|
- <li key={item.title}>
|
|
|
- <span
|
|
|
- className={`${styles.rankingItemNumber} ${
|
|
|
- i < 3 ? styles.active : ''
|
|
|
- }`}
|
|
|
- >
|
|
|
- {i + 1}
|
|
|
- </span>
|
|
|
- <span className={styles.rankingItemTitle} title={item.title}>
|
|
|
- {item.title}
|
|
|
- </span>
|
|
|
- <span>{numeral(item.total).format('0,0')}</span>
|
|
|
- </li>
|
|
|
- ))}
|
|
|
- </ul>
|
|
|
- </div>
|
|
|
- </Col>
|
|
|
- </Row>
|
|
|
- </TabPane>
|
|
|
- </Tabs>
|
|
|
- </div>
|
|
|
- </Card>
|
|
|
-
|
|
|
+ <Suspense fallback={<PageLoading />}>
|
|
|
+ <IntroduceRow loading={loading} visitData={visitData} />
|
|
|
+ </Suspense>
|
|
|
+ <Suspense fallback={null}>
|
|
|
+ <SalesCard
|
|
|
+ rangePickerValue={rangePickerValue}
|
|
|
+ salesData={salesData}
|
|
|
+ isActive={this.isActive}
|
|
|
+ handleRangePickerChange={this.handleRangePickerChange}
|
|
|
+ loading={loading}
|
|
|
+ selectDate={this.selectDate}
|
|
|
+ />
|
|
|
+ </Suspense>
|
|
|
<Row gutter={24}>
|
|
|
<Col xl={12} lg={24} md={24} sm={24} xs={24}>
|
|
|
- <Card
|
|
|
- loading={loading}
|
|
|
- bordered={false}
|
|
|
- title={
|
|
|
- <FormattedMessage
|
|
|
- id="app.analysis.online-top-search"
|
|
|
- defaultMessage="Online Top Search"
|
|
|
- />
|
|
|
- }
|
|
|
- extra={iconGroup}
|
|
|
- style={{ marginTop: 24 }}
|
|
|
- >
|
|
|
- <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(12321).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={searchData}
|
|
|
- pagination={{
|
|
|
- style: { marginBottom: 0 },
|
|
|
- pageSize: 5,
|
|
|
- }}
|
|
|
+ <Suspense fallback={null}>
|
|
|
+ <TopSearch
|
|
|
+ loading={loading}
|
|
|
+ visitData2={visitData2}
|
|
|
+ selectDate={this.selectDate}
|
|
|
+ searchData={searchData}
|
|
|
+ dropdownGroup={dropdownGroup}
|
|
|
/>
|
|
|
- </Card>
|
|
|
+ </Suspense>
|
|
|
</Col>
|
|
|
<Col xl={12} lg={24} md={24} sm={24} xs={24}>
|
|
|
- <Card
|
|
|
- loading={loading}
|
|
|
- className={styles.salesCard}
|
|
|
- bordered={false}
|
|
|
- title={
|
|
|
- <FormattedMessage
|
|
|
- id="app.analysis.the-proportion-of-sales"
|
|
|
- defaultMessage="The Proportion of Sales"
|
|
|
- />
|
|
|
- }
|
|
|
- bodyStyle={{ padding: 24 }}
|
|
|
- extra={
|
|
|
- <div className={styles.salesCardExtra}>
|
|
|
- {iconGroup}
|
|
|
- <div className={styles.salesTypeRadio}>
|
|
|
- <Radio.Group value={salesType} onChange={this.handleChangeSalesType}>
|
|
|
- <Radio.Button value="all">
|
|
|
- <FormattedMessage id="app.analysis.channel.all" defaultMessage="ALL" />
|
|
|
- </Radio.Button>
|
|
|
- <Radio.Button value="online">
|
|
|
- <FormattedMessage
|
|
|
- id="app.analysis.channel.online"
|
|
|
- defaultMessage="Online"
|
|
|
- />
|
|
|
- </Radio.Button>
|
|
|
- <Radio.Button value="stores">
|
|
|
- <FormattedMessage
|
|
|
- id="app.analysis.channel.stores"
|
|
|
- defaultMessage="Stores"
|
|
|
- />
|
|
|
- </Radio.Button>
|
|
|
- </Radio.Group>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- }
|
|
|
- style={{ marginTop: 24, minHeight: 509 }}
|
|
|
- >
|
|
|
- <h4 style={{ marginTop: 8, marginBottom: 32 }}>
|
|
|
- <FormattedMessage id="app.analysis.sales" defaultMessage="Sales" />
|
|
|
- </h4>
|
|
|
- <Pie
|
|
|
- hasLegend
|
|
|
- subTitle={<FormattedMessage id="app.analysis.sales" defaultMessage="Sales" />}
|
|
|
- total={() => <Yuan>{salesPieData.reduce((pre, now) => now.y + pre, 0)}</Yuan>}
|
|
|
- data={salesPieData}
|
|
|
- valueFormat={value => <Yuan>{value}</Yuan>}
|
|
|
- height={248}
|
|
|
- lineWidth={4}
|
|
|
+ <Suspense fallback={null}>
|
|
|
+ <ProportionSales
|
|
|
+ dropdownGroup={dropdownGroup}
|
|
|
+ salesType={salesType}
|
|
|
+ loading={loading}
|
|
|
+ salesPieData={salesPieData}
|
|
|
+ handleChangeSalesType={this.handleChangeSalesType}
|
|
|
/>
|
|
|
- </Card>
|
|
|
+ </Suspense>
|
|
|
</Col>
|
|
|
</Row>
|
|
|
-
|
|
|
- <Card
|
|
|
- loading={loading}
|
|
|
- className={styles.offlineCard}
|
|
|
- bordered={false}
|
|
|
- bodyStyle={{ padding: '0 0 32px 0' }}
|
|
|
- style={{ marginTop: 32 }}
|
|
|
- >
|
|
|
- <Tabs activeKey={activeKey} onChange={this.handleTabChange}>
|
|
|
- {offlineData.map(shop => (
|
|
|
- <TabPane tab={<CustomTab data={shop} currentTabKey={activeKey} />} key={shop.name}>
|
|
|
- <div style={{ padding: '0 24px' }}>
|
|
|
- <TimelineChart
|
|
|
- height={400}
|
|
|
- data={offlineChartData}
|
|
|
- titleMap={{
|
|
|
- y1: formatMessage({ id: 'app.analysis.traffic' }),
|
|
|
- y2: formatMessage({ id: 'app.analysis.payments' }),
|
|
|
- }}
|
|
|
- />
|
|
|
- </div>
|
|
|
- </TabPane>
|
|
|
- ))}
|
|
|
- </Tabs>
|
|
|
- </Card>
|
|
|
+ <Suspense fallback={null}>
|
|
|
+ <OfflineData
|
|
|
+ activeKey={activeKey}
|
|
|
+ loading={loading}
|
|
|
+ offlineData={offlineData}
|
|
|
+ offlineChartData={offlineChartData}
|
|
|
+ handleTabChange={this.handleTabChange}
|
|
|
+ />
|
|
|
+ </Suspense>
|
|
|
</GridContent>
|
|
|
);
|
|
|
}
|