style: 统计分布; 首页

feature/2.0-sales-trade
Lei OT 2 years ago
parent c96c23a96e
commit aec35604ee

@ -198,7 +198,7 @@ export default observer((props) => {
// layout="inline"
<Form form={form} name="advanced_search" className="orders-search-form" onFinish={onFinish} onValuesChange={onValuesChange}>
<EditableContext.Provider value={form}>
<Row gutter={10} style={{ background: '#f9fafa', margin: '0px 0px 10px 0px', padding: '16px 8px' }}>
<Row gutter={10} style={{ background: '#f9fafa', margin: '0px 0px 10px 0px', padding: '16px 8px', boxShadow: '0px 0px 3px 0px rgba(0,0,0,0.15)' }}>
{getFields({ sort, initialValue, hides, shows, fieldProps, form })}
{/* 'textAlign': 'right' */}
<Col flex="1 0 120px" style={{ padding: '0px 5px' }}>

@ -5,14 +5,14 @@ import moment from 'moment';
import { isEmpty, pick, sortBy, fixTo2Decimals, cloneDeep, unique } 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' },
'destinationCountry': { url: '/service-Analyse2/GetTradeApartByDestinationCountry' },
'tourDays': { url: '/service-Analyse2/GetTradeApartByTourDays', keySort: true },
'PML': { url: '/service-Analyse2/GetTradeApartByPML', keySort: true },
'ConfirmDays': { url: '/service-Analyse2/GetTradeApartByConfirmDays', keySort: true },
'ApplyDays': { url: '/service-Analyse2/GetTradeApartByApplyDays', keySort: true },
'PersonNum': { url: '/service-Analyse2/GetTradeApartByPersonNum', keySort: true },
'destination': { url: '/service-Analyse2/GetTradeApartByDestination', keySort: false },
'GlobalDestination': { url: '/service-Analyse2/GetTradeApartByGlobalDestination', keySort: false },
'destinationCountry': { url: '/service-Analyse2/GetTradeApartByDestinationCountry', keySort: false },
};
class Distribution {
constructor(appStore) {
@ -41,12 +41,13 @@ class Distribution {
param.DateToQ2 = DateToQ2.format(`${DATE_FORMAT} 23:59:59`);
const json = await req.fetchJSON(modelMapper[mkey].url, param);
if (json.errcode === 0) {
runInAction(() => {
const dataLength = json.result.length;
const pickResult = dataLength > 20 ? json.result.slice(0, 30) : json.result;
const dataSource = calcDiff({ result: pickResult, resultToY: json.resultToY, resultToQ: json.resultToQ }, modelMapper[mkey].keySort);
runInAction(() => {
this[mkey].loading = false;
this[mkey].originData = json.result;
const pickResult = dataLength > 20 ? json.result.slice(0, 30) : json.result;
this[mkey].dataSource = calcDiff({ result: pickResult, resultToY: json.resultToY, resultToQ: json.resultToQ });
this[mkey].dataSource = dataSource;
this.pageLoading = false;
});
}
@ -118,15 +119,14 @@ class Distribution {
/**
* 计算 同比, 环比
*/
const calcDiff = ({ result, resultToY, resultToQ }) => {
if (isEmpty(resultToY) || isEmpty(resultToQ)) {
// return result;
}
const initialDataWithAllKeys = unique([].concat(result, resultToY, resultToQ).map((ele) => `${ele.key}@${ele.label}`)).reduce((r, v) => {
const calcDiff = ({ result, resultToY, resultToQ }, keySort) => {
const initialDataWithAllKeys = unique([].concat(result, resultToY, resultToQ).map((ele) => `${ele.key}@${ele.label}`))
.reduce((r, v) => {
const [key, label] = String(v).split('@');
r.push({ key: Number(key), label, SumML: 0, ConfirmOrder: 0, SumOrder: 0, SumMLPercent: 0, ConfirmOrderPercent: 0, SumOrderPercent: 0 });
return r;
}, []).sort(sortBy('key'));
}, [])
.sort(keySort ? sortBy('key') : undefined);
const initialMapped = initialDataWithAllKeys.reduce((r, v) => ({ ...r, [v.key]: v }), {});
const resultMapped = result.reduce((r, v) => ({ ...r, [v.key]: v }), cloneDeep(initialMapped));
const resultToYMapped = resultToY.reduce((r, v) => ({ ...r, [v.key]: v }), cloneDeep(initialMapped));

@ -32,7 +32,7 @@ class Trade {
// hasKPI: !isEmpty(summary?.[dataFieldAlias.ConfirmOrder.nestkey.p]),
hasKPI: false
},
{ title: '毛利', value: summary?.SumML, KPIrate: summary?.[dataFieldAlias.SumML.nestkey.p], hasKPI: false },
{ title: '毛利', value: dataFieldAlias.SumML.formatter(summary?.SumML || 0), KPIrate: summary?.[dataFieldAlias.SumML.nestkey.p], hasKPI: false },
{ title: '完成率', value: `${summary?.[dataFieldAlias.SumML.nestkey.p] || ''}%`, hasKPI: false },
{
title: '人数',

@ -61,12 +61,14 @@ export default observer(() => {
autoFit: false,
// color: ['#f6bd16', '#E8EDF3'],
color: ['#61ddaa', '#E8EDF3'], // #7cb305
innerRadius: 0.90,
};
const RingProgressConfigQ = {
height: 50,
width: 50,
autoFit: false,
color: ['#f6bd16', '#E8EDF3'],
innerRadius: 0.90,
};
const columns = [
{ title: '', dataIndex: 'label' },
@ -76,7 +78,7 @@ export default observer(() => {
render: (v, r) => (
<>
<Row align={'middle'}>
<Col flex="1 1 100px">
<Col flex={"150px"}>
<Text strong>{v}</Text>
</Col>
<Col flex={'auto'}>
@ -99,7 +101,7 @@ export default observer(() => {
render: (v, r) => (
<>
<Row align={'middle'}>
<Col flex="1 1 100px">
<Col flex={"150px"}>
<Text strong>{dataFieldAlias.SumML.formatter(v)}</Text>
</Col>
<Col flex={'auto'}>
@ -119,12 +121,12 @@ export default observer(() => {
{
title: '团数占比',
dataIndex: 'ConfirmOrderPercent',
render: (v, r) => <RingProgress {...RingProgressConfig} percent={v / 100} />,
render: (v, r) => v ? <RingProgress {...RingProgressConfig} percent={v / 100} /> : '-',
},
{
title: '业绩占比',
dataIndex: 'SumMLPercent',
render: (v, r) => <RingProgress {...RingProgressConfig} percent={v / 100} />,
render: (v, r) => v ? <RingProgress {...RingProgressConfig} percent={v / 100} /> : '-',
},
{
title: () => <><div>去年同期</div><div>{dateStringY}</div></>,
@ -134,13 +136,13 @@ export default observer(() => {
title: '团数占比',
width: 90,
dataIndex: 'ConfirmOrderPercent',
render: (v, r) => <RingProgress {...RingProgressConfigY} percent={r.resultToY.ConfirmOrderPercent / 100} />,
render: (v, r) => r.resultToY.ConfirmOrderPercent ? <RingProgress {...RingProgressConfigY} percent={r.resultToY.ConfirmOrderPercent / 100} /> : '-',
},
{
title: '业绩占比',
width: 90,
dataIndex: 'SumMLPercent',
render: (v, r) => <RingProgress {...RingProgressConfigY} percent={r.resultToY.SumMLPercent / 100} />,
render: (v, r) => r.resultToY.SumMLPercent ? <RingProgress {...RingProgressConfigY} percent={r.resultToY.SumMLPercent / 100} /> : '-',
},
],
},
@ -152,13 +154,13 @@ export default observer(() => {
title: '团数占比',
width: 90,
dataIndex: 'ConfirmOrderPercent',
render: (v, r) => <RingProgress {...RingProgressConfigQ} percent={r.resultToQ.ConfirmOrderPercent / 100} />,
render: (v, r) => r.resultToQ.ConfirmOrderPercent ? <RingProgress {...RingProgressConfigQ} percent={r.resultToQ.ConfirmOrderPercent / 100} /> : '-',
},
{
title: '业绩占比',
width: 90,
dataIndex: 'SumMLPercent',
render: (v, r) => <RingProgress {...RingProgressConfigQ} percent={r.resultToQ.SumMLPercent / 100} />,
render: (v, r) => r.resultToQ.SumMLPercent ? <RingProgress {...RingProgressConfigQ} percent={r.resultToQ.SumMLPercent / 100} /> : '-',
},
],
},

@ -17,11 +17,11 @@ import { Line } from '@ant-design/charts';
import './home.css';
const topSeries = [
{ key: 'country', label: '国籍' },
{ key: 'dept', label: '小组' },
{ key: 'operator', label: '顾问' },
{ key: 'GuestGroupType', label: '客群类别' },
{ key: 'destination', label: '目的地' },
{ key: 'country', label: '国籍', graphVisible: true },
{ key: 'dept', label: '小组', graphVisible: true },
{ key: 'operator', label: '顾问', graphVisible: true },
{ key: 'GuestGroupType', label: '客群类别', graphVisible: false },
{ key: 'destination', label: '目的地', graphVisible: true },
];
// const iconSets = [CheckCircleTwoTone, <MoneyCollectTwoTone />, <FlagTwoTone />, <ClockCircleTwoTone />, <DashboardTwoTone />,<SmileTwoTone />,];
@ -160,7 +160,7 @@ export default observer(() => {
};
return (
<>
<Row gutter={16} style={{ margin: '-16px -8px' }}>
<Row gutter={16} style={{ margin: '-16px -8px', position: 'sticky', top: 0, zIndex: 2, }}>
{/* style={{ margin: '-16px -8px', padding: 0 }} */}
<Col className="gutter-row" span={24}>
<SearchForm
@ -239,14 +239,14 @@ export default observer(() => {
</div>
</Space>
<Row gutter={layoutProps.gutter}>
{topSeries.map((item) => (
{topSeries.map((item) => item.graphVisible ? (
<Col {...layoutProps} key={item.key}>
<Spin spinning={topData[item.key]?.loading || false}>
<h3 style={{ textAlign: 'center' }}>{item.label}</h3>
<Bullet {...BulletConfig} dataSource={topData[item.key]?.dataSource || []} itemLength={10} />
</Spin>
</Col>
))}
) : null)}
</Row>
</section>
</>

Loading…
Cancel
Save