diff --git a/src/charts/Customer_care_regular.jsx b/src/charts/Customer_care_regular.jsx
index 44fbdeb..0a462cb 100644
--- a/src/charts/Customer_care_regular.jsx
+++ b/src/charts/Customer_care_regular.jsx
@@ -6,13 +6,24 @@ import { stores_Context } from '../config';
import { observer } from 'mobx-react';
import SearchForm from './../components/search/SearchForm';
import LineWithAvg from '../components/LineWithAvg';
-import { flow } from 'mobx';
-import { TableExportBtn } from '../components/Data';
+import { toJS } from 'mobx';
+import { TableExportBtn, VSDataTag, RenderVSDataCell } from '../components/Data';
+
+import useCustomerRelationsStore from '../zustand/CustomerRelations';
+import { useShallow } from 'zustand/shallow';
+import { fixTo2Decimals } from '@haina/utils-commons';
const Customer_care_regular = () => {
- const { orders_store, date_picker_store, customer_store } = useContext(stores_Context);
+ const { date_picker_store, customer_store } = useContext(stores_Context);
const regular_data = customer_store.regular_data;
+ const [loading, loading2, searchValues, ] = useCustomerRelationsStore(useShallow((state) => [state.loading, state.loading2, state.searchValues,]));
+ const [setSearchValues] = useCustomerRelationsStore(useShallow((state) => [state.setSearchValues]));
+
+ const [regular] = useCustomerRelationsStore(useShallow((state) => [state.regular]));
+
+ const getRegularCustomer = useCustomerRelationsStore((state) => state.getRegularCustomer);
+
const columns = [
{
title: '订单号',
@@ -205,13 +216,14 @@ const Customer_care_regular = () => {
return (
-
+
{
}}
onSubmit={async (_err, obj, form, str) => {
customer_store.setSearchValues(obj, form, 'regular_data');
- regular_data.data_compare=[];
- if (obj.DateDiff1 && obj.DateDiff2){
- regular_data.isCompareLine=true;
- regular_data.showCompareSum=true;
- await customer_store.regular_customer_order();
- customer_store.regular_customer_order(false,true);
- // customer_store.regular_customer_order(true,false,true);
- // customer_store.regular_customer_order(true,true,true);
- }
- else{
- regular_data.isCompareLine=false;
- regular_data.showCompareSum=false;
- customer_store.regular_customer_order();
- // customer_store.regular_customer_order(true);
- }
+ setSearchValues(obj, form);
+ getRegularCustomer({ ...obj, IsDetail: 0 });
+ getRegularCustomer({ ...obj, IsDetail: 1 });
+
+ // regular_data.data_compare=[];
+ // if (obj.DateDiff1 && obj.DateDiff2){
+ // regular_data.isCompareLine=true;
+ // regular_data.showCompareSum=true;
+ // await customer_store.regular_customer_order();
+ // customer_store.regular_customer_order(false,true);
+ // // customer_store.regular_customer_order(true,false,true);
+ // customer_store.regular_customer_order(true,true,true);
+ // }
+ // else{
+ // regular_data.isCompareLine=false;
+ // regular_data.showCompareSum=false;
+ // customer_store.regular_customer_order();
+ // customer_store.regular_customer_order(true);
+ // }
}}
/>
@@ -247,8 +263,8 @@ const Customer_care_regular = () => {
{
title: () => (
<>
订单数{' '}
-
+
>
@@ -268,10 +284,14 @@ const Customer_care_regular = () => {
key: 'OrderNum',
render: (text, record, index) => (
<>
- {text}
- {
- {index === 0 && regular_data.total_data_tips!=='' && }
- }
+
+ {/* {text} */}
+
+ {
+
+ {index === 0 && regular.total_data_tips !== '' && }
+
+ }
>
),
},
@@ -279,46 +299,49 @@ const Customer_care_regular = () => {
title: '订单数占比',
dataIndex: 'OrderRate',
key: 'OrderRate',
- render: (text) => typeof text === 'number'?{parseFloat((text * 100).toFixed(2))}%:text,
+ render: (text, record) =>
},
{
title: '订单数占比(市场)',
dataIndex: 'OrderRate2',
key: 'OrderRate2',
- render: (text) => typeof text === 'number'?{parseFloat((text * 100).toFixed(2))}%:text,
+ render: (text, record) =>
},
{
title: '成行数',
dataIndex: 'SUCOrderNum',
key: 'SUCOrderNum',
+ render: (text, record) =>
},
{
title: '成行率',
dataIndex: 'SUCRate',
key: 'SUCRate',
- render: (text) => typeof text === 'number'?{Math.round(text * 100)}%:text,
+ render: (text, record) =>
},
{
title: '毛利',
dataIndex: 'ML',
key: 'ML',
+ render: (text, record) =>
},
{
title: '毛利占比',
dataIndex: 'OrderMLRate',
key: 'OrderMLRate',
- render: (text) => typeof text === 'number'?{parseFloat((text * 100).toFixed(2))}%:text,
+ render: (text, record) =>
},
{
title: '毛利占比(市场)',
dataIndex: 'OrderMLRate2',
key: 'OrderMLRate2',
- render: (text) => typeof text === 'number'?{parseFloat((text * 100).toFixed(2))}%:text,
+ render: (text, record) =>
},
{
title: '人数(含成人+儿童)',
dataIndex: 'PersonNum',
key: 'PersonNum',
+ render: (text, record) =>
},
]}
size="small"
@@ -327,65 +350,38 @@ const Customer_care_regular = () => {
/>
-
-
- <>
-
>
-
-
+
+
+
+
-
-
- {
- const wb = utils.table_to_book(document.getElementById('table_to_xlsx').getElementsByTagName('table')[0]);
- writeFileXLSX(wb, '老客户.xlsx');
- }}
- >
- 导出下表
-
-
-
-
record.COLI_ID}
- />
-
-
+
+
+ {
+ const wb = utils.table_to_book(document.getElementById('table_to_xlsx').getElementsByTagName('table')[0]);
+ writeFileXLSX(wb, '老客户.xlsx');
+ }}
+ >
+ 导出下表
+
+
+
+ record.COLI_ID} />
+
+
diff --git a/src/components/Data.jsx b/src/components/Data.jsx
index 1cd4732..00c446c 100644
--- a/src/components/Data.jsx
+++ b/src/components/Data.jsx
@@ -58,6 +58,23 @@ export const VSDataTag = ({ diffPercent=0, diffData=0, data1=0, data2=0, dataSuf
);
};
+/**
+ * 表格中显示数据对比
+ *
+ * @property {boolean | undefined} [showDiffData=false]
+ * @property {number} [diffPercent=0]
+ * @property {number} diffData
+ * @property {number} data1
+ * @property {number} data2
+ * @property {string} dataSuffix
+ */
+export const RenderVSDataCell = ({ showDiffData=false, data1, data2, dataSuffix = '', ...props }) => {
+ if (showDiffData) {
+ return ;
+ }
+ return {data1}{dataSuffix}
;
+};
+
/**
* 导出表格数据存为xlsx
* @property label 文件名字
diff --git a/src/zustand/CustomerRelations.js b/src/zustand/CustomerRelations.js
new file mode 100644
index 0000000..e832d61
--- /dev/null
+++ b/src/zustand/CustomerRelations.js
@@ -0,0 +1,171 @@
+import { create } from 'zustand';
+import { devtools } from 'zustand/middleware';
+import { immer } from 'zustand/middleware/immer';
+import { fetchJSON } from '@haina/utils-request';
+import { HT_HOST } from '../config';
+import { formatDate, isEmpty, sortBy } from '@haina/utils-commons';
+import { groupsMappedByKey, sitesMappedByCode, pivotBy } from './../libs/ht';
+
+const defaultParams = {};
+
+export const fetchRegularCustomer = async (params) => {
+ const _params = {
+ Website: params.WebCode || '', // CHT,AH,JH,GH,ZWQD,GH_ZWQD_HW,GHKYZG,GHKYHW,HTravel
+ DEI_SNList: params.DepartmentList || '', // 1,2,28,7
+ ApplydateCheck: params.DateType === 'applyDate' ? 1 : 0, //
+ EntrancedateCheck: params.DateType === 'startDate' ? 1 : 0, //
+ ConfirmDateCheck: params.DateType === 'confirmDate' ? 1 : 0, //
+ ApplydateStart: params.Date1 || '',
+ ApplydateEnd: params.Date2 || '',
+ EntrancedateStart: params.Date1 || '',
+ EntrancedateEnd: params.Date2 || '',
+ ConfirmdateStart: params.Date1 || '',
+ ConfirmdateEnd: params.Date2 || '',
+ IsDetail: '', //
+ IncludeTickets: '', //
+ ...params,
+ };
+ const { WebCode, DepartmentList, DateType, Date1, Date2, ...readyParams } = _params;
+ const [result1, result2] = await Promise.all([
+ fetchJSON(HT_HOST + '/service-tourdesign/RegularCusOrder', { ...defaultParams, ...readyParams }),
+ ...(params.DateDiff1 && params.IsDetail === 0
+ ? [
+ fetchJSON(HT_HOST + '/service-tourdesign/RegularCusOrder', {
+ ...defaultParams,
+ ...readyParams,
+ ApplydateStart: params.DateDiff1 || '',
+ ApplydateEnd: params.DateDiff2 || '',
+ EntrancedateStart: params.DateDiff1 || '',
+ EntrancedateEnd: params.DateDiff2 || '',
+ ConfirmdateStart: params.DateDiff1 || '',
+ ConfirmdateEnd: params.DateDiff2 || '',
+ }),
+ ]
+ : []),
+ ]);
+ if (params.IsDetail === 1) {
+ return { result1, result2 };
+ }
+ const ret = {};
+ const result1Mapped = result1.reduce((r, v) => ({ ...r, [v.ItemName]: v }), {});
+ const allKeys = [...new Set([...result1.map((e) => e.ItemName), ...result2.map((e) => e.ItemName)])];
+ const result2Mapped = result2.reduce((r, v) => ({ ...r, [v.ItemName]: v }), {});
+ const x = {};
+ allKeys.forEach((key) => {
+ x[key] = { ...(result1Mapped?.[key] || { ItemName: key }), diff: result2Mapped[key] || {} };
+ });
+ ret.result1 = Object.values(x);
+ console.log(ret);
+ return { result1: ret.result1 }; // { result1, result2 };
+};
+
+// 老客户: 日期对应的数据字段
+const dateTypeDataHelper = {
+ applyDate: 'SumOrder',
+ startDate: 'ConfirmOrder',
+ confirmDate: 'ConfirmOrder',
+};
+
+/**
+ * 构建 老客户系列数据
+ * * 用明细数据计算
+ * @param {[]} details
+ * @param {string} pivotByOrder
+ * @param {string} pivotByDate
+ * @returns
+ */
+const buildSeriesDataFromDetails = (details, pivotByOrder, pivotByDate) => {
+ const dataDetail = (details || []).map((ele) => ({
+ ...ele,
+ key: ele.COLI_ID,
+ orderState: ele.OrderState,
+ applyDate: formatDate(new Date(ele.COLI_ApplyDate)),
+ startDate: ele.COLI_OrderStartDate,
+ confirmDate: formatDate(new Date(ele.COLI_ConfirmDate)),
+ }));
+ const { data: IsOldData } = pivotBy(
+ dataDetail.filter((ele) => ele.COLI_IsOld === '是'),
+ [['COLI_IsOld'], [], pivotByDate]
+ );
+ const { data: isCusCommendData } = pivotBy(
+ dataDetail.filter((ele) => ele.COLI_IsCusCommend === '是'),
+ [['COLI_IsCusCommend'], [], pivotByDate]
+ );
+ // console.log('IsOldData====', IsOldData, '\nisCusCommend', isCusCommendData);
+ // 合并成两个系列
+ const seriesData = []
+ .concat(
+ IsOldData.map((ele) => ({ ...ele, _ylabel: '老客户' })),
+ isCusCommendData.map((ele) => ({ ...ele, _ylabel: '老客户推荐' }))
+ )
+ .sort(sortBy(pivotByDate));
+ return seriesData;
+};
+
+/**
+ * --------------------------------------------------------------------------------------------------------
+ */
+const initialState = {
+ loading: false,
+ loading2: false,
+ searchValues: {
+ DepartmentList: ['1', '2', '28', '7'].map((kk) => groupsMappedByKey[kk]),
+ WebCode: ['CHT', 'AH', 'JH', 'GH', 'ZWQD', 'GH_ZWQD_HW', 'GHKYZG', 'GHKYHW', 'HTravel'].map((kk) => sitesMappedByCode[kk]),
+ DateType: { key: 'applyDate', label: '提交日期' },
+ IncludeTickets: { key: '0', label: '不含门票' },
+ },
+ searchValuesToSub: {},
+
+ regular: { data: [], details: [], total_data_tips: '', pivotData: [], pivotY: 'SumOrder', pivotX: '' },
+};
+
+const useCustomerRelationsStore = create(
+ devtools(
+ immer((set, get) => ({
+ ...initialState,
+ reset: () => set(initialState),
+
+ setLoading: (loading) => set({ loading }),
+ setLoading2: (loading2) => set({ loading2 }),
+ setSearchValues: (obj, values) => set((state) => ({ searchValues: values, searchValuesToSub: obj })),
+ setSearchValuesToSub: (values) => set((state) => ({ searchValuesToSub: values })),
+
+ // 获取数据 ---------------------------------------------------------------------------------------------------
+
+ // 老客户
+ getRegularCustomer: async (params) => {
+ const { setLoading, setLoading2 } = get();
+ const { IsDetail } = params;
+ setLoading(true);
+ setLoading2(IsDetail === 1);
+ const pivotByOrder = dateTypeDataHelper[params.DateType];
+ const pivotByDate = params.DateType;
+ try {
+ const {result1, result2} = await fetchRegularCustomer(params);
+ set((state) => {
+ if (IsDetail === 1) {
+ state.regular.details = result1;
+
+ const dump_l = (result1 || []).filter((ele) => ele.COLI_IsOld !== '' && ele.COLI_IsCusCommend !== '').length;
+ state.regular.total_data_tips = dump_l > 0 ? `包含 ${dump_l} 条同时勾选的数据` : '';
+ /** 使用明细数据画图 */
+ const seriesData = buildSeriesDataFromDetails(result1, pivotByOrder, pivotByDate);
+ state.regular.pivotData = seriesData;
+ state.regular.pivotX = pivotByDate;
+ state.regular.pivotY = pivotByOrder;
+ } else {
+ state.regular.data = result1;
+ }
+ });
+ } catch (error) {
+ } finally {
+ setLoading(false);
+ IsDetail === 1 && setLoading2(false);
+ }
+ },
+ })),
+ { name: 'CustomerRelations' }
+ )
+);
+
+export default useCustomerRelationsStore;