From c023dd5b682a9a79b2dbcec3e7ab158f5f750b40 Mon Sep 17 00:00:00 2001 From: Lei OT Date: Thu, 15 Jan 2026 14:46:41 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20=E8=80=81=E5=AE=A2=E6=88=B7-=E5=88=86?= =?UTF-8?q?=E6=9E=90:=20=E5=9B=BD=E7=B1=8D=E6=B1=87=E6=80=BB=E8=AE=A1?= =?UTF-8?q?=E7=AE=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/charts/Customer_care_regular_pivot.jsx | 78 +++++++------------- src/components/Data.jsx | 2 +- src/stores/CustomerStore.js | 83 +++++++++++++++++----- 3 files changed, 91 insertions(+), 72 deletions(-) diff --git a/src/charts/Customer_care_regular_pivot.jsx b/src/charts/Customer_care_regular_pivot.jsx index aa6daae..fb325f6 100644 --- a/src/charts/Customer_care_regular_pivot.jsx +++ b/src/charts/Customer_care_regular_pivot.jsx @@ -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'; // 注意TdCell要提到DataTable作用域外声明 @@ -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 ( <> @@ -167,32 +143,13 @@ const CustomerCareRegularPivot = (props) => { ...ele, children: ( <> - {/*

{ele.label}-老客户, 含推荐

*/} <> - {/* {dataSource.length > 0 && pivotRow === 'operatorName' && ( - { - setIfmerge(e); - }} - /> - )} - */} - {/* - */} { customer_store.regular_data_pivot(pivotRow, sub); }} items={pivotColOptions.map((col, i) => { - // const SubjectTableComponent = subjectComponents[ele.key]; return { ...col, children: ( { }, ...columns, ]} + summary={() => { + return ( + pivotRow === 'country' && + countrySummary.map((srow) => ( + + {srow.country} + {columns.map((td) => ( + + + + ))} + + )) + ); + }} pagination={false} - />) + /> + ), }; })} /> diff --git a/src/components/Data.jsx b/src/components/Data.jsx index 3665274..f02447b 100644 --- a/src/components/Data.jsx +++ b/src/components/Data.jsx @@ -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 ; } diff --git a/src/stores/CustomerStore.js b/src/stores/CustomerStore.js index 1f8b45e..3d96a04 100644 --- a/src/stores/CustomerStore.js +++ b/src/stores/CustomerStore.js @@ -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;