perf: 老客户-分析: 国籍汇总计算

main
Lei OT 3 months ago
parent 16e6ec574a
commit c023dd5b68

@ -1,10 +1,11 @@
import { useContext, useEffect, useState } from 'react';
import { observer } from 'mobx-react';
import { toJS } from 'mobx';
import { stores_Context } from '../config';
import { Table, Row, Col, Divider, Switch, Space, Tabs, Tooltip } from 'antd';
import { InfoCircleOutlined } from '@ant-design/icons';
import SearchForm from '../components/search/SearchForm';
import { TableExportBtn, VSTag } from '../components/Data';
import { RenderVSDataCell, TableExportBtn, VSTag } from '../components/Data';
import { fixTo2Decimals, isEmpty } from '@haina/utils-commons';
// TdCellDataTable
@ -39,8 +40,8 @@ const pivotColOptions = [
const CustomerCareRegularPivot = (props) => {
const { date_picker_store: searchFormStore, customer_store } = useContext(stores_Context);
const { formValues, formValuesToSub, siderBroken } = searchFormStore;
const { loading, pivotResult, filterColValues, rawData } = customer_store.sales_regular_data;
const { loading, pivotResult, filterColValues, rawData, countrySummary } = customer_store.sales_regular_data;
// console.log('', countrySummary);
const [pivotRow, setPivotRow] = useState('operatorName');
const [pivotCol, setPivotCol] = useState('hasOld');
const [pivotColLabel, setPivotColLabel] = useState('老客户+推荐');
@ -57,36 +58,10 @@ const CustomerCareRegularPivot = (props) => {
useEffect(() => {
if ( ! ifmerge) {
// setDataSource(pageData[pivotRow].data);
setDataSource(pivotResult);
// setDataForExport(
// // pageData[pivotRow].data.reduce(
// pivotResult.reduce(
// (r, c) =>
// r.concat(
// [{ ...c, children: undefined }],
// (c?.children || [])
// .reduce((rc, ele) => rc.concat([{ ...ele, [pivotRow]: ele.rowLabel }], [{ ...ele.vsData, [pivotRow]: ele.vsData.rowLabel, vsData: {} }]), [])
// .filter((ele) => ele.SumOrder !== undefined)
// ),
// []
// )
// );
setDataForExportS(pivotResult.reduce((r, c) => r.concat([{...c, children: undefined}], [{ ...c.vsData, vsData: {} }]), []).filter((ele) => ele.SumOrder !== undefined));
} else {
// setDataSource(pageData[pivotRow].mergedData);
// setDataForExport(
// pageData[pivotRow].mergedData.reduce(
// (r, c) =>
// r.concat(
// [{ ...c, children: undefined }],
// c.children.reduce((rc, ele) => rc.concat([{ ...ele, operatorName: ele.rowLabel }], [{ ...ele.vsData, operatorName: ele.vsData.rowLabel, vsData: {} }]), [])
// .filter((ele) => ele.SumOrder !== undefined)
// ),
// []
// )
// );
// setDataForExportS(pageData[pivotRow].mergedData.reduce((r, c) => r.concat([{...c, children: undefined}], [{ ...c.vsData, vsData: {} }]), []).filter((ele) => ele.SumOrder !== undefined));
//
}
return () => {};
@ -130,9 +105,10 @@ const CustomerCareRegularPivot = (props) => {
{ key: 'ConfirmPersonNum', title: '✔人数(SUM)', dataIndex: 'ConfirmPersonNum', width: '5em', render: (v, r) => renderVS(v, r, 'ConfirmPersonNum') },
{ key: 'confirmTourdays', title: '✔团天数(AVG)', dataIndex: 'confirmTourdays', width: '5em', render: (v, r) => renderVS(v, r, 'confirmTourdays') },
{ key: 'SumML', title: '预计毛利', dataIndex: 'SumML', width: '5em', render: (v, r) => renderVS(v, r, 'SumML') }, // SumML_txt
{ key: 'ConfirmRates', title: '成交率', dataIndex: 'ConfirmRates_txt', width: '5em', render: (v, r) => renderVS(v, r, 'ConfirmRates') },
{ key: 'ConfirmRates', title: '成交率', dataIndex: 'ConfirmRates_txt', width: '5em', render: (v, r) => renderVS(v, r, 'ConfirmRates'), suffix: '%' },
{ key: 'SingleML', title: '单团毛利', dataIndex: 'SingleML', width: '5em', render: (v, r) => renderVS(v, r, 'SingleML') },
].map(c => ({...c, sorter: (a, b) => (a[c.key] - b[c.key])}));
return (
<>
<Row gutter={16} className={siderBroken ? '' : 'sticky-top'}>
@ -167,32 +143,13 @@ const CustomerCareRegularPivot = (props) => {
...ele,
children: (
<>
{/* <h2>{ele.label}-老客户, 含推荐</h2> */}
<>
<Divider orientation={'right'} style={{backgroundColor: '#fff', margin: 0, padding: '10px 0'}} >
{/* {dataSource.length > 0 && pivotRow === 'operatorName' && (
<Switch
unCheckedChildren="各账户"
checkedChildren="合并"
key={'openOrMerge'}
checked={ifmerge}
onChange={(e) => {
setIfmerge(e);
}}
/>
)}
<Divider type={'vertical'} /> */}
<TableExportBtn
btnTxt="导出明细"
label={`${formValuesToSub.Date1}-老客户-明细`}
{...{ columns: [{ title: ele.labelX || ele.label, dataIndex: pivotRow, key: pivotRow }, ...rowColumns], dataSource: rawData }}
/>
{/* <Divider type={'vertical'} />
<TableExportBtn
btnTxt="导出下表-展开"
label={`${formValuesToSub.Date1}-${ele.label}.老客户`}
{...{ columns: [{ title: ele.label, dataIndex: pivotRow, key: pivotRow }, ...columns], dataSource: dataForExport }}
/> */}
<Divider type={'vertical'} />
<TableExportBtn
btnTxt="导出下表"
@ -209,12 +166,11 @@ const CustomerCareRegularPivot = (props) => {
customer_store.regular_data_pivot(pivotRow, sub);
}}
items={pivotColOptions.map((col, i) => {
// const SubjectTableComponent = subjectComponents[ele.key];
return {
...col,
children: (
<Table
sticky
sticky={{ offsetHeader: 88 }}
dataSource={dataSource}
loading={loading}
columns={[
@ -229,8 +185,24 @@ const CustomerCareRegularPivot = (props) => {
},
...columns,
]}
summary={() => {
return (
pivotRow === 'country' &&
countrySummary.map((srow) => (
<Table.Summary.Row key={srow.key}>
<Table.Summary.Cell index1={0}><b>{srow.country}</b></Table.Summary.Cell>
{columns.map((td) => (
<Table.Summary.Cell key={td.key}>
<RenderVSDataCell data1={srow[td.dataIndex]} data2={srow.vsData?.[td.dataIndex]} showDiffData={toJS(formValuesToSub.DateDiff1)} dataSuffix={td.suffix} />
</Table.Summary.Cell>
))}
</Table.Summary.Row>
))
);
}}
pagination={false}
/>)
/>
),
};
})}
/>

@ -68,7 +68,7 @@ export const VSDataTag = ({ diffPercent=0, diffData=0, data1=0, data2=0, dataSuf
* @property {number} data2
* @property {string} dataSuffix
*/
export const RenderVSDataCell = ({ showDiffData=false, data1, data2, dataSuffix = '', ...props }) => {
export const RenderVSDataCell = ({ showDiffData=false, data1=0, data2=0, dataSuffix = '', ...props }) => {
if (showDiffData) {
return <VSDataTag data1={data1} data2={data2} dataSuffix={dataSuffix} {...props} />;
}

@ -2,7 +2,7 @@ import {makeAutoObservable, runInAction, toJS } from "mobx";
import { fetchJSON } from '@haina/utils-request';
import * as config from "../config";
import { groupsMappedByKey, sitesMappedByCode, pivotBy } from './../libs/ht';
import { sortBy, formatPercent, groupBy, isEmpty, uniqWith, formatPercentToFloat } from "@haina/utils-commons";
import { sortBy, formatPercent, groupBy, isEmpty, uniqWith, formatPercentToFloat, fixTo2Decimals } from "@haina/utils-commons";
import { show_vs_tag, } from "./../utils/commons";
import moment from 'moment';
@ -14,6 +14,26 @@ const getDetailData = async (param) => {
return json.errcode === 0 ? json.result : [];
};
const calcSummaryRow = (data1, data2) => {
const summaryFields = ['ConfirmOrder', 'SumOrder', 'SumML', 'transactions', 'SumPersonNum', 'ConfirmPersonNum', 'ConfirmOrderKPIvalue', 'OrderKPIvalue', 'MLKPIvalue'];
const xSummary = summaryFields.reduce((r, skey) => ({ ...r, [skey]: data1.reduce((a, c) => a + c[skey], 0) }), {});
xSummary.ConfirmRates = xSummary.SumOrder ? fixTo2Decimals((xSummary.ConfirmOrder / xSummary.SumOrder) * 100) : 0;
xSummary.ConfirmRates_txt = xSummary.ConfirmRates; // + '%';
xSummary.confirmTourdays = '-';
xSummary.SingleML = '-';
xSummary._data = data1;
const xSummary2 = summaryFields.reduce((r, skey) => ({ ...r, [skey]: data2.reduce((a, c) => a + c[skey], 0) }), {});
xSummary2.ConfirmRates = xSummary2.SumOrder ? fixTo2Decimals((xSummary2.ConfirmOrder / xSummary2.SumOrder) * 100) : 0;
xSummary2.ConfirmRates_txt = xSummary2.ConfirmRates; // + '%';
xSummary2.confirmTourdays = '-';
xSummary2.SingleML = '-';
xSummary2._data = data2;
xSummary.vsData = xSummary2;
return xSummary;
};
class CustomerStore {
constructor(rootStore) {
@ -476,6 +496,7 @@ class CustomerStore {
// country: { loading: false, data: [], rawData: [], mergedData: [], filterColValues: [] },
// },
pivotResult: [],
countrySummary: [],
filterColValues: [],
rawDataArr: [],
};
@ -556,31 +577,36 @@ class CustomerStore {
const [result1, result2] = this.sales_regular_data.rawDataArr;
// const allRows = Array.from(new Set([...result1.filterHasOld.map(row=>row[pivotRow]), ...result2.filterHasOld.map(row=>row[pivotRow])]));
// console.log(' ------ allRows', allRows);
const [{ pivotResult: pivot1, rowValues: rowValues1 }, { pivotResult: pivot2, rowValues: rowValues2 }] = [result1, result2].map(_result => {
const [{ pivotResult: pivot1, rowValues: rowValues1 }, { pivotResult: pivot2, rowValues: rowValues2 }] = [result1, result2].map((_result) => {
const dataColField = pivotCol.replace('_txt', '');
const rawData = pivotCol === 'hasOld' ? _result.filterHasOld : _result.filterHasOld.filter((ele) => ele[dataColField] === '1');
const { data: pivotResult, columnValues: [[rowValues,], columnsKeys, dateKeys] } = pivotBy(rawData, [[pivotRow, pivotCol], [], []]);
const {
data: pivotResult,
columnValues: [[rowValues], columnsKeys, dateKeys],
} = pivotBy(rawData, [[pivotRow, pivotCol], [], []]);
return { pivotResult, rowValues };
});
const allRowValues = Array.from(new Set([...rowValues1, ...rowValues2]));
// console.log(' ------ xx', rowValues1);
const rows1 = groupBy(pivot1, pivotRow);
const rows2 = groupBy(pivot2, pivotRow);
const pivotResultWithCompare = isEmpty(pivot2) ? pivot1 : allRowValues.reduce((r, rowName) => {
const _default = { [pivotRow]: rowName, rowLabel: rows1?.[rowName]?.rowLabel || rows2?.[rowName]?.rowLabel, children: rows1?.[rowName], key: rowName};
const operatorRow = {...(rows1?.[rowName]?.[0] || _default), vsData: rows2?.[rowName]?.[0] || {}};
// 展开的两项: '老客户', '老客户推荐'
// const series1Children = rows1?.[rowName]?.[0]?.children || [];
// const series2Children = rows2?.[rowName]?.[0]?.children || [];
// const children = allTypes.reduce((r, type) => {
// const _default = { [pivotRow]: type, rowLabel: type, key: type};
// const _typeRow = series1Children.find(sc => sc[pivotRow] === type) || _default;
// const _typeVSRow = series2Children.find(sc => sc[pivotRow] === type) || {};
// return r.concat({..._typeRow, vsData: _typeVSRow});
// }, []);
// operatorRow.children = children;
return r.concat(operatorRow);
}, []);
const pivotResultWithCompare = isEmpty(pivot2)
? pivot1
: allRowValues.reduce((r, rowName) => {
const _default = { [pivotRow]: rowName, rowLabel: rows1?.[rowName]?.rowLabel || rows2?.[rowName]?.rowLabel, children: rows1?.[rowName], key: rowName };
const operatorRow = { ...(rows1?.[rowName]?.[0] || _default), vsData: rows2?.[rowName]?.[0] || {} };
// 展开的两项: '老客户', '老客户推荐'
// const series1Children = rows1?.[rowName]?.[0]?.children || [];
// const series2Children = rows2?.[rowName]?.[0]?.children || [];
// const children = allTypes.reduce((r, type) => {
// const _default = { [pivotRow]: type, rowLabel: type, key: type};
// const _typeRow = series1Children.find(sc => sc[pivotRow] === type) || _default;
// const _typeVSRow = series2Children.find(sc => sc[pivotRow] === type) || {};
// return r.concat({..._typeRow, vsData: _typeVSRow});
// }, []);
// operatorRow.children = children;
return r.concat(operatorRow);
}, []);
// console.log(' ------ pivot1', pivot1, '\npivot2', pivot2, '\npivotResultWithCompare', pivotResultWithCompare);
const filterColValues = uniqWith(
@ -588,6 +614,27 @@ class CustomerStore {
(a, b) => JSON.stringify(a) === JSON.stringify(b)
).sort((a, b) => a.text.localeCompare(b.text, 'zh-CN'));
if (pivotRow === 'country') {
const aseanKK = ['新加坡', '马来西亚', '印度尼西亚', '菲律宾', '越南', '泰国', '文莱', '柬埔寨', '东帝汶', '老挝', '缅甸'];
const [asean1, asean2] = [
pivot1.filter((ele) => aseanKK.includes(ele.country)),
pivot2.filter((ele) => aseanKK.includes(ele.country)),
];
const aseanSummary = calcSummaryRow(asean1, asean2);
aseanSummary.key = '东南亚11国';
aseanSummary.country = '东南亚11国';
const eurusdKK = ['美国', '加拿大', '澳大利亚', '英国'];
const [eurusd1, eurusd2] = [
pivot1.filter((ele) => eurusdKK.includes(ele.country)),
pivot2.filter((ele) => eurusdKK.includes(ele.country)),
];
const eurusdSummary = calcSummaryRow(eurusd1, eurusd2);
eurusdSummary.key = '欧美4国';
eurusdSummary.country = '欧美4国';
this.sales_regular_data.countrySummary = [aseanSummary, eurusdSummary];
}
this.sales_regular_data.pivotResult = pivotResultWithCompare;
this.sales_regular_data.filterColValues = filterColValues;

Loading…
Cancel
Save