diff --git a/src/stores/CustomerStore.js b/src/stores/CustomerStore.js
index 2a53605..c5a98d0 100644
--- a/src/stores/CustomerStore.js
+++ b/src/stores/CustomerStore.js
@@ -2,7 +2,7 @@ import {makeAutoObservable, runInAction} from "mobx";
import { fetchJSON } from '../utils/request';
import * as config from "../config";
import { groupsMappedByKey, sitesMappedByCode, pivotBy } from './../libs/ht';
-import { sortBy, show_vs_tag, formatPercent } from "../utils/commons";
+import { sortBy, show_vs_tag, formatPercent, groupBy, isEmpty } from "../utils/commons";
import moment from 'moment';
/**
@@ -168,13 +168,13 @@ class CustomerStore {
if (isCompare){
return {
...item,
- _ylabel: date_picker_store.start_date_cp.format(config.DATE_FORMAT)+ '-' +date_picker_store.end_date_cp.format(config.SMALL_DATETIME_FORMAT) + item._ylabel
+ _ylabel: date_picker_store.start_date_cp.format(config.DATE_FORMAT)+ '-' +date_picker_store.end_date_cp.format(config.SMALL_DATETIME_FORMAT) + item._ylabel
};
}
else{
return {
...item,
- _ylabel: date_picker_store.start_date.format(config.DATE_FORMAT)+ '-' +date_picker_store.end_date.format(config.SMALL_DATETIME_FORMAT) + item._ylabel
+ _ylabel: date_picker_store.start_date.format(config.DATE_FORMAT)+ '-' +date_picker_store.end_date.format(config.SMALL_DATETIME_FORMAT) + item._ylabel
};
}
});
@@ -203,7 +203,7 @@ class CustomerStore {
this.regular_data.pivotData = seriesCompareData; // { IsOldData, isCusCommendData, };
this.regular_data.pivotY = pivotByOrder;
this.regular_data.pivotX = pivotByDate;
- }
+ }
}
else{
this.regular_data.detail_loading = false;
@@ -226,7 +226,7 @@ class CustomerStore {
this.regular_data.pivotData = seriesData; // { IsOldData, isCusCommendData, };
this.regular_data.pivotY = pivotByOrder;
this.regular_data.pivotX = pivotByDate;
- }
+ }
} else {
if (isCompare){
const result = [];
@@ -237,15 +237,15 @@ class CustomerStore {
result.push({
ItemName: item1.ItemName,
OrderNum: show_vs_tag(formatPercent((item1.OrderNum-item2.OrderNum)/(item2.OrderNum===0?1:item2.OrderNum)),
- item1.OrderNum-item2.OrderNum,item1.OrderNum,item2.OrderNum),
+ item1.OrderNum-item2.OrderNum,item1.OrderNum,item2.OrderNum),
SUCOrderNum: show_vs_tag(formatPercent((item1.SUCOrderNum-item2.SUCOrderNum)/(item2.SUCOrderNum===0?1:item2.SUCOrderNum)),
- item1.SUCOrderNum-item2.SUCOrderNum,item1.SUCOrderNum,item2.SUCOrderNum),
+ item1.SUCOrderNum-item2.SUCOrderNum,item1.SUCOrderNum,item2.SUCOrderNum),
SUCRate: show_vs_tag(formatPercent((item1.SUCRate-item2.SUCRate)/(item2.SUCRate===0?1:item2.SUCRate)),
- formatPercent(item1.SUCRate-item2.SUCRate),formatPercent(item1.SUCRate),formatPercent(item2.SUCRate)),
+ formatPercent(item1.SUCRate-item2.SUCRate),formatPercent(item1.SUCRate),formatPercent(item2.SUCRate)),
ML: show_vs_tag(formatPercent((item1.ML-item2.ML)/(item2.ML===0?1:item2.ML)),
- (item1.ML-item2.ML).toFixed(2),item1.ML,item2.ML),
+ (item1.ML-item2.ML).toFixed(2),item1.ML,item2.ML),
PersonNum: show_vs_tag(formatPercent((item1.PersonNum-item2.PersonNum)/(item2.PersonNum===0?1:item2.PersonNum)),
- item1.PersonNum-item2.PersonNum,item1.PersonNum,item2.PersonNum),
+ item1.PersonNum-item2.PersonNum,item1.PersonNum,item2.PersonNum),
});
}
}
@@ -410,10 +410,70 @@ class CustomerStore {
},
};
- get_sales_regular_data = async (param) => {
+ // 销售-老客户
+ get_sales_regular_data_vs = async (param) => {
this.sales_regular_data.loading = true;
+ const hasCompare = !isEmpty(param.DateDiff1);
+ const [result1, result2] = await Promise.all([
+ this.get_sales_regular_data(param),
+ hasCompare ? this.get_sales_regular_data({...param, Date1: param.DateDiff1, Date2: param.DateDiff2}) : { mergeDataBySales: [], mergeDataBySalesAccount: [], filterHasOld: []},
+ ]);
+
+ const allTypes = ['老客户', '老客户推荐'];
+ // 独立的账户
+ const allSales = Array.from(new Set([...result1.mergeDataBySales.map(row=>row.operatorName), ...result2.mergeDataBySales.map(row=>row.operatorName)]));
+ const sales1 = groupBy(result1.mergeDataBySales, 'operatorName');
+ const sales2 = groupBy(result2.mergeDataBySales, 'operatorName');
+ const mergeDataBySales = allSales.reduce((r, sale) => {
+ const _default = { operatorName: sale, rowLabel: sales1?.[sale]?.rowLabel || sales2?.[sale]?.rowLabel, children: sales1?.[sale]?.children || [], key: sale};
+ const operatorRow = {...(sales1?.[sale]?.[0] || _default), vsData: sales2?.[sale]?.[0] || {}};
+ // 展开的两项: '老客户', '老客户推荐'
+ const series1Children = sales1?.[sale]?.[0]?.children || [];
+ const series2Children = sales2?.[sale]?.[0]?.children || [];
+ const children = allTypes.reduce((r, type) => {
+ const _default = { operatorName: type, rowLabel: type, key: type};
+ const _typeRow = series1Children.find(sc => sc.operatorName === type) || _default;
+ const _typeVSRow = series2Children.find(sc => sc.operatorName === type) || {};
+ return r.concat({..._typeRow, vsData: _typeVSRow});
+ }, []);
+ operatorRow.children = children;
+ return r.concat(operatorRow);
+ }, []);
+ // 合并顾问的账户
+ const allSalesMerged = Array.from(new Set([...result1.mergeDataBySalesAccount.map(row=>row.operatorName), ...result2.mergeDataBySalesAccount.map(row=>row.operatorName)]));
+ const salesM1 = groupBy(result1.mergeDataBySalesAccount, 'operatorName');
+ const salesM2 = groupBy(result2.mergeDataBySalesAccount, 'operatorName');
+ const mergeDataBySalesAccount = allSalesMerged.reduce((r, sale) => {
+ const _default = { operatorName: sale, rowLabel: salesM1?.[sale]?.rowLabel || salesM2?.[sale]?.rowLabel, children: salesM1?.[sale]?.children || [], key: sale};
+ const operatorRow = {...(salesM1?.[sale]?.[0] || _default), vsData: salesM2?.[sale]?.[0] || {}};
+ // 展开的两项: '老客户', '老客户推荐'
+ const series1Children = salesM1?.[sale]?.[0]?.children || [];
+ const series2Children = salesM2?.[sale]?.[0]?.children || [];
+ const children = allTypes.reduce((r, type) => {
+ const _default = { operatorName: type, rowLabel: type, key: type};
+ const _typeRow = series1Children.find(sc => sc.operatorName === type) || _default;
+ const _typeVSRow = series2Children.find(sc => sc.operatorName === type) || {};
+ return r.concat({..._typeRow, vsData: _typeVSRow});
+ }, []);
+ operatorRow.children = children;
+ return r.concat(operatorRow);
+ }, []);
+
+ this.sales_regular_data.loading = false;
+ this.sales_regular_data.data = mergeDataBySales;
+ this.sales_regular_data.mergedData = mergeDataBySalesAccount;
+ this.sales_regular_data.rawData = [].concat(result1.filterHasOld, result2.filterHasOld);
+
+ };
+
+ get_sales_regular_data = async (param) => {
+ const seriesKey = `${param.Date1}至${param.Date2}`;
const rawData = await getDetailData({...param, IncludeTickets: 1});
- const filterHasOld = rawData.filter(ele => (ele.IsOld === '1' || ele.isCusCommend === '1')).map(e => ({...e, operatorNameB: e.operatorName.replace(/\([^)]*\)/gi, '').toLowerCase()}));
+ const filterHasOld = rawData.filter(ele => (ele.IsOld === '1' || ele.isCusCommend === '1')).map(e => ({
+ ...e,
+ seriesKey,
+ operatorNameB: e.operatorName.replace(/\([^)]*\)/gi, '').toLowerCase(),
+ }));
const { data: hasOldData, } = pivotBy(filterHasOld, [['hasOld', 'operatorName'], [], []]);
const { data: IsOldData, } = pivotBy(filterHasOld.filter(ele => ele.IsOld === '1'), [['operatorName', 'IsOld_txt', ], [], []]);
@@ -422,9 +482,10 @@ class CustomerStore {
// console.log('data====', rawData, '\ncolumnValues', columnValues, '\nsummaryRows', summaryRows, '\nsummaryColumns', summaryColumns, '\nsummaryMix', summaryMix, '\nhasOld',filterHasOld);
const mergeDataBySales = hasOldData.map((ele) => ({
...ele,
+ seriesKey,
children: [].concat(
- IsOldData.filter((ele1) => ele1.operatorName === ele.operatorName).map(o => ({...o, operatorName: o.IsOld_txt, key: o.rowLabel})),
- isCusCommendData.filter((ele2) => ele2.operatorName === ele.operatorName).map(o => ({...o, operatorName: o.isCusCommend_txt, key: o.rowLabel}))
+ IsOldData.filter((ele1) => ele1.operatorName === ele.operatorName).map(o => ({...o, operatorName: o.IsOld_txt, key: o.rowLabel, seriesKey,})),
+ isCusCommendData.filter((ele2) => ele2.operatorName === ele.operatorName).map(o => ({...o, operatorName: o.isCusCommend_txt, key: o.rowLabel, seriesKey,}))
),
}));
@@ -435,18 +496,19 @@ class CustomerStore {
const mergeDataBySalesAccount = hasOldDataSales.map((ele) => ({
...ele,
operatorName: ele.operatorNameB,
+ seriesKey,
children: [].concat(
- IsOldDataSales.filter((ele1) => ele1.operatorNameB === ele.operatorNameB).map(o => ({...o, operatorName: o.IsOld_txt, key: o.rowLabel})),
- isCusCommendDataSales.filter((ele2) => ele2.operatorNameB === ele.operatorNameB).map(o => ({...o, operatorName: o.isCusCommend_txt, key: o.rowLabel}))
+ IsOldDataSales.filter((ele1) => ele1.operatorNameB === ele.operatorNameB).map(o => ({...o, operatorName: o.IsOld_txt, key: o.rowLabel, seriesKey,})),
+ isCusCommendDataSales.filter((ele2) => ele2.operatorNameB === ele.operatorNameB).map(o => ({...o, operatorName: o.isCusCommend_txt, key: o.rowLabel, seriesKey,}))
),
}));
// console.log('IsOldDataSales====', IsOldDataSales, '\nisCusCommendDataSales', isCusCommendDataSales);
// console.log('mergeDataBySalesAccount====', mergeDataBySalesAccount);
-
- this.sales_regular_data.loading = false;
- this.sales_regular_data.data = mergeDataBySales;
- this.sales_regular_data.mergedData = mergeDataBySalesAccount;
- this.sales_regular_data.rawData = filterHasOld;
+ return { mergeDataBySales, mergeDataBySalesAccount, filterHasOld };
+ // this.sales_regular_data.loading = false;
+ // this.sales_regular_data.data = mergeDataBySales;
+ // this.sales_regular_data.mergedData = mergeDataBySalesAccount;
+ // this.sales_regular_data.rawData = filterHasOld;
};
setSearchValues(obj, values, target) {
diff --git a/src/views/SalesCustomerCareRegular.jsx b/src/views/SalesCustomerCareRegular.jsx
index ebc44c8..33b8c6a 100644
--- a/src/views/SalesCustomerCareRegular.jsx
+++ b/src/views/SalesCustomerCareRegular.jsx
@@ -1,10 +1,10 @@
import { createContext, useContext, useEffect, useState } from 'react';
import { observer } from 'mobx-react';
import { stores_Context } from '../config';
-import { Table, Row, Col, Divider, Button, Switch } from 'antd';
+import { Table, Row, Col, Divider, Button, Switch, Space } from 'antd';
import SearchForm from '../components/search/SearchForm';
-import { TableExportBtn } from './../components/Data';
-import { uniqWith, groupBy } from './../utils/commons';
+import { TableExportBtn, VSTag } from './../components/Data';
+import { uniqWith, groupBy, fixTo2Decimals, isEmpty } from './../utils/commons';
// 注意TdCell要提到DataTable作用域外声明
const TdCell = (tdprops) => {
@@ -37,8 +37,19 @@ const SalesCustomerCareRegular = (props) => {
// ).sort((a, b) => a.text.localeCompare(b.text));
// setOPIFilters(allOPI1);
setDataSource(pageData.data);
- setDataForExport(pageData.data.reduce((r, c) => r.concat([{...c, children: undefined}], c.children.map(ele => ({...ele, operatorName: ele.rowLabel}))), []));
- setDataForExportS(pageData.data.reduce((r, c) => r.concat([{...c, children: undefined}]), []));
+ setDataForExport(
+ pageData.data.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.data.reduce((r, c) => r.concat([{...c, children: undefined}], [{ ...c.vsData, vsData: {} }]), []).filter((ele) => ele.SumOrder !== undefined));
} else {
// const allOPI1 = uniqWith(
// pageData.mergedData.map((rr) => ({ text: rr.operatorName, value: rr.operatorName })),
@@ -46,8 +57,18 @@ const SalesCustomerCareRegular = (props) => {
// ).sort((a, b) => a.text.localeCompare(b.text));
// setOPIFilters(allOPI1);
setDataSource(pageData.mergedData);
- setDataForExport(pageData.mergedData.reduce((r, c) => r.concat([{...c, children: undefined}], c.children.map(ele => ({...ele, operatorName: ele.rowLabel}))), []));
- setDataForExportS(pageData.mergedData.reduce((r, c) => r.concat([{...c, children: undefined}]), []));
+ setDataForExport(
+ pageData.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.mergedData.reduce((r, c) => r.concat([{...c, children: undefined}], [{ ...c.vsData, vsData: {} }]), []).filter((ele) => ele.SumOrder !== undefined));
}
return () => {
@@ -57,6 +78,7 @@ const SalesCustomerCareRegular = (props) => {
const rowColumns = [
+ { title: '日期区间', dataIndex: 'seriesKey', key: 'seriesKey' },
{ title: '顾问', dataIndex: 'operatorName', key: 'operatorName' },
{ title: '订单号', dataIndex: 'o_id', key: 'o_id' },
{ title: '预定日期', dataIndex: 'applyDate', key: 'applyDate' },
@@ -73,17 +95,30 @@ const SalesCustomerCareRegular = (props) => {
{ title: '来源', dataIndex: 'SourceType', key: 'SourceType' },
{ title: '页面类型', dataIndex: 'COLI_LineClass', key: 'COLI_LineClass' },
];
+ const calcDelta = (r, key) => !isEmpty(Number(r.vsData[key])) ? fixTo2Decimals((Number(r[key] || 0) - Number(r.vsData[key]))/Number(r.vsData[key]) *100) : null;
+ const renderVS = (v, r, key) => {
+ const delta = calcDelta(r, key);
+ return <>
+