feat: 统计分布

feature/2.0-sales-trade
Lei OT 2 years ago
parent a56ff400e7
commit 2cac464363

@ -10,7 +10,7 @@ import {
DollarOutlined,
AreaChartOutlined,
WechatOutlined,
UserOutlined, FlagOutlined,
UserOutlined, FlagOutlined, PieChartOutlined
} from '@ant-design/icons';
import { Layout, Menu, Image, Spin } from 'antd';
import { BrowserRouter, Route, Routes, NavLink } from 'react-router-dom';
@ -36,6 +36,7 @@ import { stores_Context } from './config';
import { observer } from 'mobx-react';
import ExchangeRate from './charts/ExchangeRate';
import KPI from './views/KPI';
import Distribution from './views/Distribution';
const App = () => {
const { Content, Footer, Sider } = Layout;
@ -121,6 +122,7 @@ const App = () => {
],
},
{ key: 'kpi', label: <NavLink to="/kpi">目标</NavLink>, icon: <FlagOutlined /> },
{ key: 'distribution', label: <NavLink to="/distribution">统计分布</NavLink>, icon: <PieChartOutlined /> },
];
return (
@ -162,6 +164,7 @@ const App = () => {
<Routes>
<Route path="/" element={<Home />} />
<Route path="/kpi" element={<KPI />} />
<Route path="/distribution" element={<Distribution />} />
<Route element={<ProtectedRoute auth={['admin', 'director_bu', 'marketing']} />}>
<Route path="/orders" element={<Orders />} />
<Route path="/orders_sub/:ordertype/:ordertype_sub/:ordertype_title" element={<Orders_sub />} />

@ -56,6 +56,7 @@ class DictData {
data = {};
operator = { loading: false, dataSource: [] };
country = { loading: false, dataSource: [] };
vendor = { loading: false, dataSource: [] };
creditcardbilltype = { loading: false, dataSource: [] };
}

@ -0,0 +1,61 @@
import { makeAutoObservable, runInAction, toJS } from 'mobx';
import * as req from '../utils/request';
import { isEmpty, sortBy } from '../utils/commons';
const modelMapper = {
'tourDays': { url: '/service-Analyse2/GetTradeApartByTourDays' },
'PML': { url: '/service-Analyse2/GetTradeApartByPML' },
'ConfirmDays': { url: '/service-Analyse2/GetTradeApartByConfirmDays' },
'ApplyDays': { url: '/service-Analyse2/GetTradeApartByApplyDays' },
'PersonNum': { url: '/service-Analyse2/GetTradeApartByPersonNum' },
'destination': { url: '/service-Analyse2/GetTradeApartByDestination' },
'GlobalDestination': { url: '/service-Analyse2/GetTradeApartByGlobalDestination' },
};
class Distribution {
constructor(appStore){
this.appStore = appStore;
makeAutoObservable(this);
}
async getData(param){
const mkey = this.curTab;
this[mkey] = { loading: true, dataSource: [] };
const json = await req.fetchJSON(modelMapper[mkey].url, param);
if (json.errcode === 0) {
runInAction(() => {
const dataLength = json.result.length;
this[mkey].loading = false;
this[mkey].originData = json.result;
this[mkey].dataSource = dataLength > 20 ? json.result.slice(0, 30) : json.result;
});
}
return this[mkey];
}
resetData() {
this.tourDays = { loading: false, dataSource: [] };
this.PML = { loading: false, dataSource: [] };
this.ConfirmDays = { loading: false, dataSource: [] };
this.ApplyDays = { loading: false, dataSource: [] };
this.PersonNum = { loading: false, dataSource: [] };
this.destination = { loading: false, dataSource: [] };
this.GlobalDestination = { loading: false, dataSource: [] };
}
curTab = 'tourDays';
setCurTab(v) {
this.curTab = v;
}
pageLoading = false;
tourDays = { loading: false, dataSource: [] };
PML = { loading: false, dataSource: [] };
ConfirmDays = { loading: false, dataSource: [] };
ApplyDays = { loading: false, dataSource: [] };
PersonNum = { loading: false, dataSource: [] };
destination = { loading: false, dataSource: [] };
GlobalDestination = { loading: false, dataSource: [] };
}
export default Distribution;

@ -13,6 +13,7 @@ import CustomerServicesStore from "./CustomerServices";
import TradeStore from "./Trade";
import KPI from "./KPI";
import DictData from "./DictData";
import Distribution from "./Distribution";
class Index {
constructor() {
this.dashboard_store = new DashboardStore(this);
@ -29,6 +30,7 @@ class Index {
this.TradeStore = new TradeStore(this);
this.KPIStore = new KPI(this);
this.DictDataStore = new DictData(this);
this.DistributionStore = new Distribution(this);
makeAutoObservable(this);
}

@ -0,0 +1,118 @@
import { useContext, useEffect, useMemo } from 'react';
import { observer } from 'mobx-react';
import { stores_Context } from '../config';
import { Row, Col, Spin, Space, Radio, Tabs, Table } from 'antd';
import { RingProgress } from '@ant-design/plots';
import SearchForm from './../components/search/SearchForm';
import "./kpi.css";
import { empty } from '../utils/commons';
const apartOptions = [
{ key: 'tourDays', value: 'tourDays', label: '团天数', },
{ key: 'PML', value: 'PML', label: '单团毛利', },
{ key: 'ConfirmDays', value: 'ConfirmDays', label: '成团周期', },
{ key: 'ApplyDays', value: 'ApplyDays', label: '预定周期', },
{ key: 'PersonNum', value: 'PersonNum', label: '人等', },
{ key: 'destination', value: 'destination', label: '国内目的地', },
{ key: 'GlobalDestination', value: 'GlobalDestination', label: '海外目的地', },
];
export default observer((props) => {
const { date_picker_store: searchFormStore, DistributionStore } = useContext(stores_Context);
const { formValues, formValuesToSub } = searchFormStore;
const { curTab } = DistributionStore;
const pageRefresh = (obj) => {
DistributionStore.getData({
DateType: 'applyDate',
Date1: searchFormStore.start_date.startOf('year').format('YYYY-MM-DD'),
Date2: searchFormStore.end_date.endOf('year').format('YYYY-MM-DD 23:59'),
...(obj || formValuesToSub),
});
};
useEffect(() => {
if (empty(DistributionStore[curTab].dataSource)) {
pageRefresh();
}
}, [curTab]);
useEffect(() => {
DistributionStore.resetData();
return () => {};
}, [formValuesToSub]);
const onTabsChange = (tab) => {
DistributionStore.setCurTab(tab);
};
const RingProgressConfig = {
height: 60,
width: 60,
autoFit: false,
// percent: Number(_)/100,
color: ['#5B8FF9', '#E8EDF3'],
};
const columns = [
{
title: '',
dataIndex: 'label',
},
{ title: '团数', dataIndex: 'ConfirmOrder'},
{ title: '业绩', dataIndex: 'SumML', render1: (v) => `1`},
{ title: '团数占比', dataIndex: 'ConfirmOrderPercent', render: (v) => <RingProgress {...RingProgressConfig} percent={v/100} /> },
{ title: '业绩占比', dataIndex: 'SumMLPercent', render: (v) => <RingProgress {...RingProgressConfig} percent={v/100} />},
];
return (
<>
<Row gutter={16} style={{ margin: '-16px -8px' }}>
{/* style={{ margin: '-16px -8px', padding: 0 }} */}
<Col className="gutter-row" span={24}>
<SearchForm
defaultValue={{
initialValue: {
...formValues,
},
shows: ['DateType', 'DepartmentList', 'WebCode', 'IncludeTickets', 'years'],
fieldProps: {
DepartmentList: { show_all: true },
WebCode: { show_all: true },
years: { hide_vs: true },
},
}}
onSubmit={(_err, obj, form, str) => {
pageRefresh(obj);
}}
/>
</Col>
</Row>
<section>
<Tabs
onChange={onTabsChange}
type="card"
items={apartOptions.map((ele, i) => {
// const ObjectItemPanel = objectComponents[ele.key];
return {
...ele,
children: (
<Spin spinning={DistributionStore.pageLoading}>
{/* <ObjectItemPanel title={ele.label} {...{ curObject, onSearchSubmit, objects: retObjects }} /> */}
<Table
id="table_to_xlsx_sale"
dataSource={DistributionStore[curTab].dataSource}
columns={columns}
size="small"
rowKey={(record) => record.label}
loading={DistributionStore[curTab].loading}
pagination={false}
scroll={{ x: '100%' }}
/>
</Spin>
),
};
})}
/>
</section>
</>
);
});
Loading…
Cancel
Save