perf: 三峡,酒店: 合计

main
Lei OT 2 months ago
parent 3b51ae8d08
commit f532f138ff

@ -30,20 +30,24 @@ export const VSTag = (props) => {
/**
* 导出表格数据存为xlsx
* @property label 文件名字
* @property columns 表格列
* @property dataSource 表格数据
* @property btnTxt 按钮文字
*/
export const TableExportBtn = (props) => {
const output_name = `${props.label}`;
export const TableExportBtn = ({label, columns, dataSource, btnTxt, ...props}) => {
const output_name = `${label}`;
const [columnsMap, setColumnsMap] = useState([]);
const [summaryRow, setSummaryRow] = useState({});
useEffect(() => {
const r1 = props.columns.reduce((r, v) => ({
const r1 = columns.reduce((r, v) => ({
...r,
...(v.children ? v.children.reduce((rc, vc, ci) => ({
...rc,
...(vc?.titleX ? {[`${v?.titleX || v.title},${vc.titleX}`]: vc.titleX } : {[(v?.titleX || v.title) + (ci || '')]: `${vc?.titleX || vc?.title || ''}`}),
}), {}) : {})
}), {});
const flatCols = props.columns.flatMap((v, k) =>
const flatCols = columns.flatMap((v, k) =>
v.children ? v.children.map((vc, ci) => ({ ...vc, title: `${v?.titleX || v.title}` + (vc?.titleX ? `,${vc.titleX}` : (ci || '')) })) : {...v, title: `${v?.titleX || v.title}`}
);
// .filter((c) => c.dataIndex)
@ -56,14 +60,14 @@ export const TableExportBtn = (props) => {
// console.log('summaryRow', r1);
return () => {};
}, [props.columns]);
}, [columns]);
const onExport = () => {
if (isEmpty(props.dataSource)) {
if (isEmpty(dataSource)) {
message.warning('无结果.');
return false;
}
const data = props.dataSource.map((item) => {
const data = dataSource.map((item) => {
const itemMapped = columnsMap.reduce((sv, kset) => {
const render_val = typeof kset?.render === 'function' ? kset.render('', item) : null;
const data_val = kset?.dataIndex ? (Array.isArray(kset.dataIndex) ? getNestedValue(item, kset.dataIndex) : item[kset.dataIndex]) : undefined;
@ -88,7 +92,7 @@ export const TableExportBtn = (props) => {
disabled={false}
onClick={onExport}
>
{props.btnTxt || '导出excel'}
{btnTxt || '导出excel'}
</Button>
);
};

@ -84,10 +84,7 @@ class HotelCruise {
this.cruise.loading = true;
this.cruise.dataSource = [];
const _queryParam = objectMapper(param, paramKeyMapped);
const queryParam = omit({ ...this.searchValuesToSub, ..._queryParam }, [
'DepartmentList', 'orderStatus', 'keyword', 'Date1', 'Date2', 'DateDiff1', 'DateDiff2',
'cruiseDirection', 'cruiseBookType', 'country', 'agency',
]);
const queryParam = omit({ ...this.searchValuesToSub, ..._queryParam }, Object.keys(paramKeyMapped));
queryParam.Compare = isEmpty(param.DateDiff1) ? '' : '1';
const res = await fetchCruiseData(queryParam);
const resCP =
@ -95,13 +92,29 @@ class HotelCruise {
? res
: (res || []).map((ele) => ({
...ele,
// 计算 增长率 = (当前值 - 上次值) / 上次值 * 100
TotalNumPercent: ele.CPTotalNum ? fixTo2Decimals(((ele.TotalNum - ele.CPTotalNum) / ele.CPTotalNum) * 100) : '-',
TotalPersonNumPercent: ele.CPTotalPersonNum ? fixTo2Decimals(((ele.TotalPersonNum - ele.CPTotalPersonNum) / ele.CPTotalPersonNum) * 100) : '-',
TotalProfitPercent: ele.CPTotalProfit ? fixTo2Decimals(((ele.TotalProfit - ele.CPTotalProfit) / ele.CPTotalProfit) * 100) : '-',
}));
const summaryRow = ['TotalNum', 'TotalPersonNum', 'TotalProfit', 'CPTotalNum', 'CPTotalPersonNum', 'CPTotalProfit'].reduce(
(r, skey) => ({
...r,
[skey]: resCP.reduce((a, c) => a + c[skey], 0),
}),
{ ProductName: '合计' }
);
const summaryDelta = ['TotalNum', 'TotalPersonNum', 'TotalProfit'].reduce(
(r, skey) => ({
...r,
[`${skey}Percent`]: queryParam.Compare === '' ? null : fixTo2Decimals(((summaryRow[skey] - summaryRow[`CP${skey}`]) / summaryRow[`CP${skey}`]) * 100),
}),
{}
);
runInAction(() => {
this.cruise.loading = false;
this.cruise.dataSource = resCP;
this.cruise.summaryRow = { ...summaryRow, ...summaryDelta };
});
return this.cruise;
}
@ -110,10 +123,7 @@ class HotelCruise {
this.hotel.loading = true;
this.hotel.dataSource = [];
const _queryParam = objectMapper(param, paramKeyMapped);
const queryParam = omit({ ...this.searchValuesToSub, ..._queryParam }, [
'DepartmentList','orderStatus','keyword','Date1','Date2','DateDiff1','DateDiff2','DateType',
'hotelStar','hotelRecommandRate','hotelBookType','countryArea',
]);
const queryParam = omit({ ...this.searchValuesToSub, ..._queryParam }, Object.keys(paramKeyMapped));
queryParam.Compare = isEmpty(param.DateDiff1) ? '0' : '1';
const _res = await fetchHotelData(queryParam);
const res = (_res || []).map((ele) => ({ ...ele, RecommendRate_100: fixTo2Decimals(ele.RecommendRate * 100) + '%' }));
@ -127,9 +137,30 @@ class HotelCruise {
RecommendRateDelta: fixTo2Decimals((ele.RecommendRate - (ele.CPRecommendRate || 0)) * 100),
CPRecommendRate_100: fixTo2Decimals(ele.CPRecommendRate * 100) + '%',
}));
const summaryRow = ['TotalNum', 'RecomendNum', ].reduce(
(r, skey) => ({
...r,
[skey]: resCP.reduce((a, c) => a + c[skey], 0),
[`CP${skey}`]: resCP.reduce((a, c) => a + c[`CP${skey}`], 0),
}),
{ CityName: '合计' }
);
summaryRow.RecommendRate = fixTo2Decimals(summaryRow.RecomendNum/summaryRow.TotalNum);
summaryRow.RecommendRate_100 = fixTo2Decimals(summaryRow.RecommendRate * 100) + '%';
summaryRow.CPRecommendRate = fixTo2Decimals(summaryRow.CPRecomendNum/summaryRow.CPTotalNum);
summaryRow.CPRecommendRate_100 = fixTo2Decimals(summaryRow.CPRecommendRate * 100) + '%';
const summaryDelta = ['TotalNum', 'RecomendNum', ].reduce(
(r, skey) => ({
...r,
[`${skey}Percent`]: queryParam.Compare === '0' ? null : fixTo2Decimals(((summaryRow[skey] - summaryRow[`CP${skey}`]) / summaryRow[`CP${skey}`]) * 100),
}),
{}
);
summaryDelta.RecommendRateDelta = queryParam.Compare === '0' ? undefined : fixTo2Decimals((summaryRow.RecommendRate - (summaryRow.CPRecommendRate || 0)) * 100);
runInAction(() => {
this.hotel.loading = false;
this.hotel.dataSource = resCP;
this.hotel.summaryRow = { ...summaryRow, ...summaryDelta };
});
}
@ -150,8 +181,8 @@ class HotelCruise {
this.searchValuesToSub = obj;
}
cruise = { loading: false, dataSource: [] };
hotel = { loading: false, dataSource: [] };
cruise = { loading: false, dataSource: [], summaryRow: {} };
hotel = { loading: false, dataSource: [], summaryRow: {} };
resetData = () => {
this.results.loading = false;
for (const key of Object.keys(this.results)) {

@ -1,70 +1,123 @@
import React, { Children, useContext, useState } from 'react';
import React, { useContext } from 'react';
import { observer } from 'mobx-react';
import { stores_Context } from '../config';
import moment from 'moment';
import { Row, Col, Table, Select, Space, Typography, Progress, Spin, Divider, Button, Switch } from 'antd';
import { Row, Col, Table, Space, Typography } from 'antd';
import SearchForm from './../components/search/SearchForm';
import { VSTag, TableExportBtn } from './../components/Data';
import { VSTag } from './../components/Data';
import { CruiseAgency } from './../libs/ht';
const {Text} = Typography;
const { Text } = Typography;
export default observer((props) => {
const { sale_store, date_picker_store: searchFormStore } = useContext(stores_Context);
const { customerServicesStore, HotelCruiseStore, date_picker_store } = useContext(stores_Context);
const { loading, dataSource } = HotelCruiseStore.cruise;
const { date_picker_store: searchFormStore } = useContext(stores_Context);
const { HotelCruiseStore, date_picker_store } = useContext(stores_Context);
const { loading, dataSource, summaryRow } = HotelCruiseStore.cruise;
const { formValues, siderBroken } = searchFormStore;
const tableSorter = (a, b, colName) => (a[colName] - b[colName]);
const tableSorter = (a, b, colName) => a[colName] - b[colName];
const tableProps = {
size: 'small',
bordered: true, pagination: false,
bordered: true,
pagination: false,
columns: [
{ title: '产品', dataIndex: 'ProductName', key: 'ProductName' },
{ title: '产品', children: [{ title: summaryRow.ProductName, dataIndex: 'ProductName', key: 'ProductName' }] },
{
title: '房间数',
dataIndex: 'TotalNum',
key: 'TotalNum',
sorter: (a, b) => tableSorter(a, b, 'TotalNum'),
render: (v, r) => (
<>
<Space direction={'vertical'}>
<Text strong>
{v}
{r.CPTotalNum ? <Text type="secondary"> VS {r.CPTotalNum}</Text> : null}
</Text>
{r.CPTotalNum && <VSTag diffPercent={r.TotalNumPercent} />}
</Space>
</>
),
children: [
{
title: (
<>
<Space direction={'vertical'}>
<Text strong>
{summaryRow.TotalNum}
{summaryRow.TotalNumPercent ? <Text type="secondary"> VS {summaryRow.CPTotalNum}</Text> : null}
</Text>
{summaryRow.TotalNumPercent && <VSTag diffPercent={summaryRow.TotalNumPercent} />}
</Space>
</>
),
dataIndex: 'TotalNum',
key: 'TotalNum',
render: (v, r) => (
<>
<Space direction={'vertical'}>
<Text strong>
{v}
{r.CPTotalNum ? <Text type="secondary"> VS {r.CPTotalNum}</Text> : null}
</Text>
{r.CPTotalNum && <VSTag diffPercent={r.TotalNumPercent} />}
</Space>
</>
),
},
],
},
{ title: '人数', dataIndex: 'TotalPersonNum', key: 'TotalPersonNum',
{
title: '人数',
sorter: (a, b) => tableSorter(a, b, 'TotalPersonNum'),
render: (v, r) => (
<>
<Space direction={'vertical'}>
<Text strong>
{v}
{r.CPTotalPersonNum ? <Text type="secondary"> VS {r.CPTotalPersonNum}</Text> : null}
</Text>
{r.CPTotalNum && <VSTag diffPercent={r.TotalPersonNumPercent} />}
</Space>
</>
),},
{ title: '总利润', dataIndex: 'TotalProfit', key: 'TotalProfit',
children: [
{
title: (
<>
<Space direction={'vertical'}>
<Text strong>
{summaryRow.TotalPersonNum}
{summaryRow.TotalPersonNumPercent ? <Text type="secondary"> VS {summaryRow.CPTotalPersonNum}</Text> : null}
</Text>
{summaryRow.TotalPersonNumPercent && <VSTag diffPercent={summaryRow.TotalPersonNumPercent} />}
</Space>
</>
),
dataIndex: 'TotalPersonNum',
key: 'TotalPersonNum',
render: (v, r) => (
<>
<Space direction={'vertical'}>
<Text strong>
{v}
{r.CPTotalPersonNum ? <Text type="secondary"> VS {r.CPTotalPersonNum}</Text> : null}
</Text>
{r.CPTotalNum && <VSTag diffPercent={r.TotalPersonNumPercent} />}
</Space>
</>
),
},
],
},
{
title: '总利润',
sorter: (a, b) => tableSorter(a, b, 'TotalProfit'),
render: (v, r) => (
<>
<Space direction={'vertical'}>
<Text strong>
{v}
{r.CPTotalProfit ? <Text type="secondary"> VS {r.CPTotalProfit}</Text> : null}
</Text>
{r.CPTotalNum && <VSTag diffPercent={r.TotalProfitPercent} />}
</Space>
</>
), },
children: [
{
title: (
<>
<Space direction={'vertical'}>
<Text strong>
{summaryRow.TotalProfit}
{summaryRow.TotalProfitPercent ? <Text type="secondary"> VS {summaryRow.CPTotalProfit}</Text> : null}
</Text>
{summaryRow.TotalProfitPercent && <VSTag diffPercent={summaryRow.TotalProfitPercent} />}
</Space>
</>
),
dataIndex: 'TotalProfit',
key: 'TotalProfit',
render: (v, r) => (
<>
<Space direction={'vertical'}>
<Text strong>
{v}
{r.CPTotalProfit ? <Text type="secondary"> VS {r.CPTotalProfit}</Text> : null}
</Text>
{r.CPTotalNum && <VSTag diffPercent={r.TotalProfitPercent} />}
</Space>
</>
),
},
],
},
// { title: '', dataIndex: '', key: '' },
// { title: '', dataIndex: '', key: '' },
// { title: '', dataIndex: '', key: '' },
@ -83,8 +136,14 @@ export default observer((props) => {
},
// 'countryArea',
shows: [
'DepartmentList', 'orderStatus', 'dates', 'keyword', 'cruiseDirection', 'agency',
'cruiseBookType', 'country', // 'roomsRange', 'personRange'
'DepartmentList',
'orderStatus',
'dates',
'keyword',
'cruiseDirection',
'agency',
'cruiseBookType',
'country', // 'roomsRange', 'personRange'
],
sort: { keyword: 101, agency: 110, cruiseDirection: 102, country: 104 },
fieldProps: {
@ -104,7 +163,7 @@ export default observer((props) => {
</Col>
</Row>
<section>
<Table {...tableProps} {...{loading, dataSource}} rowKey={(record) => record.ProductName} />
<Table {...tableProps} {...{ loading, dataSource }} rowKey={(record) => record.ProductName} />
</section>
</>
);

@ -7,69 +7,114 @@ import { VSTag, TableExportBtn } from './../components/Data';
const { Text } = Typography;
export default observer((props) => {
const { sale_store, date_picker_store: searchFormStore } = useContext(stores_Context);
const { customerServicesStore, date_picker_store, HotelCruiseStore } = useContext(stores_Context);
const { loading, dataSource } = HotelCruiseStore.hotel;
const { date_picker_store: searchFormStore } = useContext(stores_Context);
const { date_picker_store, HotelCruiseStore } = useContext(stores_Context);
const { loading, dataSource, summaryRow } = HotelCruiseStore.hotel;
const { formValues, siderBroken } = searchFormStore;
const tableSorter = (a, b, colName) => (a[colName] - b[colName]);
const tableSorter = (a, b, colName) => a[colName] - b[colName];
const tableProps = {
size: 'small',
bordered: true,
pagination: false,
columns: [
{ title: '目的地', dataIndex: 'CityName', key: 'CityName' },
{ title: '目的地', children: [{ title: summaryRow.CityName, dataIndex: 'CityName', key: 'CityName' }] },
{
title: '总间夜',
dataIndex: 'TotalNum',
key: 'TotalNum',
sorter: (a, b) => tableSorter(a, b, 'TotalNum'),
render: (v, r) => (
<>
<Space direction={'vertical'}>
<Text strong>
{v}
{r.CPTotalNum ? <Text type="secondary"> VS {r.CPTotalNum}</Text> : null}
</Text>
{r.CPTotalNum && <VSTag diffPercent={r.TotalNumPercent} />}
</Space>
</>
),
children: [
{
title: (
<>
<Space direction={'vertical'}>
<Text strong>
{summaryRow.TotalNum}
{summaryRow.TotalNumPercent ? <Text type="secondary"> VS {summaryRow.CPTotalNum}</Text> : null}
</Text>
{summaryRow.TotalNumPercent && <VSTag diffPercent={summaryRow.TotalNumPercent} />}
</Space>
</>
),
dataIndex: 'TotalNum',
key: 'TotalNum',
render: (v, r) => (
<>
<Space direction={'vertical'}>
<Text strong>
{v}
{r.CPTotalNum ? <Text type="secondary"> VS {r.CPTotalNum}</Text> : null}
</Text>
{r.CPTotalNum && <VSTag diffPercent={r.TotalNumPercent} />}
</Space>
</>
),
},
],
},
{
title: '主推',
dataIndex: 'RecomendNum',
key: 'RecomendNum',
sorter: (a, b) => tableSorter(a, b, 'RecomendNum'),
render: (v, r) => (
<>
<Space direction={'vertical'}>
<Text strong>
{v}
{r.CPRecomendNum ? <Text type="secondary"> VS {r.CPRecomendNum}</Text> : null}
</Text>
{r.CPRecomendNum && <VSTag diffPercent={r.RecomendNumPercent} />}
</Space>
</>
),
children: [
{
title: (
<>
<Space direction={'vertical'}>
<Text strong>
{summaryRow.RecomendNum}
{summaryRow.RecomendNumPercent ? <Text type="secondary"> VS {summaryRow.CPRecomendNum}</Text> : null}
</Text>
{summaryRow.RecomendNumPercent && <VSTag diffPercent={summaryRow.RecomendNumPercent} />}
</Space>
</>
),
dataIndex: 'RecomendNum',
key: 'RecomendNum',
render: (v, r) => (
<>
<Space direction={'vertical'}>
<Text strong>
{v}
{r.CPRecomendNum ? <Text type="secondary"> VS {r.CPRecomendNum}</Text> : null}
</Text>
{r.CPRecomendNum && <VSTag diffPercent={r.RecomendNumPercent} />}
</Space>
</>
),
},
],
},
{
title: '使用比例',
dataIndex: 'RecommendRate_100',
key: 'RecommendRate_100',
render: (v, r) => (
<>
<Space direction={'vertical'}>
<Text strong>
{v}
{r.RecommendRateDelta !== undefined && <Text type="secondary"> VS {r.CPRecommendRate_100}</Text>}
</Text>
{r.RecommendRateDelta !== undefined && <VSTag diffPercent={r.RecommendRateDelta} />}
</Space>
</>
),
children: [
{
title: (
<>
<Space direction={'vertical'}>
<Text strong>
{summaryRow.RecommendRate_100}
{summaryRow.RecommendRateDelta ? <Text type="secondary"> VS {summaryRow.CPRecommendRate_100}</Text> : null}
</Text>
{summaryRow.RecommendRateDelta && <VSTag diffPercent={summaryRow.RecommendRateDelta} />}
</Space>
</>
),
dataIndex: 'RecommendRate_100',
key: 'RecommendRate_100',
render: (v, r) => (
<>
<Space direction={'vertical'}>
<Text strong>
{v}
{r.RecommendRateDelta !== undefined && <Text type="secondary"> VS {r.CPRecommendRate_100}</Text>}
</Text>
{r.RecommendRateDelta !== undefined && <VSTag diffPercent={r.RecommendRateDelta} />}
</Space>
</>
),
},
],
},
],
};

Loading…
Cancel
Save