perf: 数据透视: +目的地国籍. 途径的计算会重复

feature/hotel-cruise
Lei OT 2 years ago
parent e59c1e11bd
commit 5dafa48ab3

@ -1,4 +1,4 @@
import { fixTo4Decimals, fixTo1Decimals, fixToInt, groupBy, sortBy, cloneDeep, pick, unique, flush, fixTo2Decimals } from '../utils/commons';
import { fixTo4Decimals, fixTo1Decimals, fixToInt, groupBy, sortBy, cloneDeep, pick, unique, flush, fixTo2Decimals, isEmpty } from '../utils/commons';
/**
* 事业部
@ -176,10 +176,25 @@ export const KPISubjects = [
* @param {any[]} groupbyKeys
* @returns
*/
export const pivotBy = (data, [rows, columns, date]) => {
export const pivotBy = (_data, [rows, columns, date]) => {
console.time('pivot3----');
console.log('pivotBy', [rows, columns, date]);
const groupbyKeys = flush([].concat(rows, columns, [date]));
// 数组的字段值, 拆分处理
let data = cloneDeep(_data);
if (groupbyKeys.includes('destinationCountry_AsJOSN')) {
data = _data.reduce((r, v, i) => {
const vjson = isEmpty(v.destinationCountry_AsJOSN) ? [] : v.destinationCountry_AsJOSN;
const xv = (vjson).reduce((rv, cv, vi) => {
rv.push({...v, destinationCountry_AsJOSN: cv, key: vi === 0 ? v.key : `${v.key}@${cv}`});
return rv;
}, []);
r = r.concat(xv);
return r;
}, []);
}
const getKeys = (keys) => keys.map((keyField) => [...new Set(data.map((f) => f[keyField]))]);
const [rowsKeys, columnsKeys, dateKeys] = [getKeys(rows), getKeys(columns), [getKeys([date])[0].filter(s => s)]];
// console.log('rowsKeys', rowsKeys, 'columnsKeys', columnsKeys, 'dateKeys', dateKeys);
@ -298,7 +313,7 @@ export const pivotBy = (data, [rows, columns, date]) => {
const summaryColumns = transposeData(columns, columnsData, ['rows', rows]);
console.timeEnd('pivot3----');
return { data: pivotResult, columnValues: [rowsKeys, columnsKeys, dateKeys], summaryRows, summaryColumns };
return { data: pivotResult, columnValues: [rowsKeys, columnsKeys, dateKeys], summaryRows, summaryColumns, pivotKeys: groupbyKeys };
};
// todo: 优化 pivotBy 速度

@ -2,7 +2,7 @@ import { useContext, useEffect, useState } from 'react';
import { observer } from 'mobx-react';
import { useParams, useLocation } from 'react-router-dom';
import { stores_Context } from '../config';
import { Row, Col, Spin, Table, Select, Typography, Card, Button, Space, Divider } from 'antd';
import { Row, Col, Spin, Table, Select, Typography, Card, Button, Space, Divider, Alert } from 'antd';
import { cloneDeep, groupBy, isEmpty, omit, pick, sortBy, unique, cartesianProductArray } from '../utils/commons';
import { dataFieldAlias, pivotBy } from '../libs/ht';
import SearchForm from '../components/search/SearchForm';
@ -24,14 +24,15 @@ const filterFields = [
// { key: 'operatorName', label: '' },
{ key: 'WebCode', label: '来源站点' },
// todo: , ,
{ key: 'destinationCountry_AsJOSN', label: '目的地国籍' },
];
const filterFieldsMapped = filterFields.reduce((r, v) => ({ ...r, [v.key]: v }), {});
/** 预设的选项, 只有行 */
const quickOptions = [
// { label: '×', fields: [['country'], ['productType']] },
{ label: '[ 产品×客群 ]', fields: [['productType', 'guestGroupType'], []] },
{ label: '[ 国籍×客群 ]', fields: [['country', 'guestGroupType'], []] },
{ label: '[ 客群×目的地国籍 ]', fields: [['guestGroupType', 'destinationCountry_AsJOSN'], []] },
// { label: '[ × ]×[ ]', fields: [['country', 'guestGroupType'], []] },
];
@ -100,6 +101,8 @@ export default observer((props) => {
const [pivotDateColumns, setPivotDateColumns] = useState([[], []]);
const [pivotDateColumnsValues, setPivotDateColumnsValues] = useState([[], []]);
const [showPassCountryTips, setShowPassCountryTips] = useState(false);
useEffect(() => {
calcDataByDate();
resetX();
@ -143,8 +146,9 @@ export default observer((props) => {
*/
const calcDataByDate = (_rawData) => {
// console.log(';;;;;', pivotDateColumns);
const { data, columnValues, summaryRows, summaryColumns } = pivotBy(_rawData || rawData, [].concat(pivotDateColumns, [curXfield]));
const { data, columnValues, summaryRows, summaryColumns, pivotKeys } = pivotBy(_rawData || rawData, [].concat(pivotDateColumns, [curXfield]));
// console.log('data====', data, '\ncolumnValues', columnValues, '\nsummaryRows', summaryRows, '\nsummaryColumns', summaryColumns);
setShowPassCountryTips(pivotKeys.includes('destinationCountry_AsJOSN'));
setDataBeforePick(data.sort(sortBy(curXfield)));
// 线
setDataSource(data.sort(sortBy(curXfield)));
@ -195,7 +199,7 @@ export default observer((props) => {
const [rightFields, setRightFields] = useState(filterFields);
const [rowFields, setRowFields] = useState([]);
const [columnFields, setColumnFields] = useState([]);
const [rowSelection, setRowSelection] = useState();
const [rowSelection, setRowSelection] = useState([]);
const [columnSelection, setColumnSelection] = useState();
//
const quickOpt = (i) => {
@ -355,7 +359,7 @@ export default observer((props) => {
return (
<div key={pathname}>
<Row gutter={16} className={siderBroken ? "" : "sticky-top"}>
<Row gutter={16} className={siderBroken ? '' : 'sticky-top'}>
<Col className="gutter-row" span={24}>
<SearchForm
defaultValue={{
@ -384,16 +388,21 @@ export default observer((props) => {
title={'透视选项'}
extra={
<Row gutter={3}>
<Col flex={'0 0 auto'}><Text type={'secondary'}>预设:</Text></Col>
<Col flex={'0 0 auto'}>
<Text type={'secondary'}>预设:</Text>
</Col>
{quickOptions.map((ele, elei) => (
<Col key={ele.label}>
<Button key={ele.label} onClick={() => quickOpt(elei)} type={'primary'} ghost size={'small'}>
{ele.label}
</Button> </Col>
</Button>
</Col>
))}
<Col><Button key={'reset-quick'} onClick={resetFields} type={'primary'} ghost size={'small'}>
<Col>
<Button key={'reset-quick'} onClick={resetFields} type={'primary'} ghost size={'small'}>
重置
</Button></Col>
</Button>
</Col>
</Row>
}
>
@ -495,6 +504,13 @@ export default observer((props) => {
</Select>
</Col>
<Col span={24}>
<Row gutter={16} align={'bottom'} className="mt-1">
<Col span={24}>
{showPassCountryTips && (
<Alert message="途径的国家将会重复计算" type="warning" showIcon />
)}
</Col>
</Row>
{/* {columnFields.length > 0
? cloneDeep(pivotDateColumnsValues)
.slice(rowFields.length)

Loading…
Cancel
Save