diff --git a/src/views/Orders.jsx b/src/views/Orders.jsx index 703a470..e80e4f6 100644 --- a/src/views/Orders.jsx +++ b/src/views/Orders.jsx @@ -254,8 +254,12 @@ class Orders extends Component { const table_data = orders_store.orderCountData_Form ? this.format_data(orders_store.orderCountData_Form) : []; const data_source = orders_store.orderCountData ? orders_store.orderCountData : []; const avg_line_y = Math.round(orders_store.avgLine1); - const pie_data = comm.empty(orders_store.orderCountData_Form) ? [] : orders_store.orderCountData_Form.ordercount1.filter(ele => ele.OrderTypeSN); // 饼图的显示 - const pie_data2 = comm.empty(orders_store.orderCountData_Form) ? [] : orders_store.orderCountData_Form.ordercount2.filter(ele => ele.OrderTypeSN); + const pie_data = comm.empty(orders_store.orderCountData_Form) + ? [] + : orders_store.orderCountData_Form.ordercount1.map((ele) => ({ ...ele, YJLYx: comm.price_to_number(ele.YJLY) })); // 饼图的显示 + const pie_data2 = comm.empty(orders_store.orderCountData_Form) + ? [] + : orders_store.orderCountData_Form.ordercount2.map((ele) => ({ ...ele, YJLYx: comm.price_to_number(ele.YJLY) })); const config = { data: data_source, @@ -327,7 +331,7 @@ class Orders extends Component { colorField: "OrderType", radius: 0.8, label: { - type: "spider", + type: "outer", content: "{name} {value} \t {percentage}", }, legend: false, // 不显示图例 @@ -497,10 +501,12 @@ class Orders extends Component { /> - + + - + + diff --git a/src/views/biz/BizOrder.jsx b/src/views/biz/BizOrder.jsx index f3b7078..ee4d320 100644 --- a/src/views/biz/BizOrder.jsx +++ b/src/views/biz/BizOrder.jsx @@ -1,6 +1,6 @@ import { useContext } from 'react'; import { Row, Col, Tabs, Table, Divider, Spin, Checkbox, Space } from 'antd'; -import { ContainerOutlined, BlockOutlined, SmileOutlined, MobileOutlined, CustomerServiceOutlined } from '@ant-design/icons'; +import { ContainerOutlined, BlockOutlined, SmileOutlined, MobileOutlined, CustomerServiceOutlined, IeOutlined } from '@ant-design/icons'; import { Line, Pie } from '@ant-design/charts'; import { NavLink } from 'react-router-dom'; import * as comm from '../../utils/commons'; @@ -19,7 +19,7 @@ const BizOrder = observer(() => { const [searchValues, setSearchValues] = useBizOrderStore(useShallow((state) => [state.searchValues, state.setSearchValues])); const [activeTab, setActiveTab] = useBizOrderStore(useShallow((state) => [state.activeTab, state.setActiveTab])); - const [loading, onTabChange] = useBizOrderStore(useShallow((state) => [state.loading, state.onTabChange])); + const [loading, typeLoading, onTabChange] = useBizOrderStore(useShallow((state) => [state.loading, state.typeLoading,state.onTabChange])); const orderCountDataRaw = useBizOrderStore((state) => state.orderCountDataRaw); const [orderCountDataLines, avgLineValue] = useBizOrderStore(useShallow((state) => [state.orderCountDataLines, state.avgLineValue])); @@ -104,7 +104,7 @@ const BizOrder = observer(() => { radius: 0.8, label: { type: 'outer', - content: '{name} {value} \n {percentage}', + content: '{name} {value} \t {percentage}', }, legend: false, // 不显示图例 interactions: [ @@ -291,6 +291,15 @@ const BizOrder = observer(() => { ), }, + { + key: 'webcode', + label: ( + + + 来源站点 + + ), + }, // { // key: 'Product', // label: ( @@ -404,7 +413,7 @@ const BizOrder = observer(() => { ...ele, children: ( <> - +
@@ -425,14 +434,17 @@ const BizOrder = observer(() => { 包含空值 */} - + - - - - + + + + {showDiff && + + + } diff --git a/src/views/biz/reports/TrainsUpsell.jsx b/src/views/biz/reports/TrainsUpsell.jsx index eb32443..c89c158 100644 --- a/src/views/biz/reports/TrainsUpsell.jsx +++ b/src/views/biz/reports/TrainsUpsell.jsx @@ -1,6 +1,6 @@ import { useContext } from 'react'; import { Row, Col, Table, Spin, Space, Divider } from 'antd'; -import { Funnel, Pie } from '@ant-design/charts'; +import { Funnel, Pie, Sunburst } from '@ant-design/charts'; import * as comm from '../../../utils/commons'; import SearchForm from '../../../components/search/SearchForm'; @@ -9,22 +9,37 @@ import { observer } from 'mobx-react'; import { toJS } from 'mobx'; import { stores_Context } from '../../../config'; import { useShallow } from 'zustand/shallow'; -import useTrainsStore from '../../../zustand/Trains'; +import useTrainsStore, { SERVICETYPE_TRAINSBOOKING, FORM_TRAINSUPSELL } from '../../../zustand/Trains'; +const buildSunburstData = (data1) => { + const total1 = (data1?.total || []).map((item) => { + return { ...item, name: item.label, value: item.YJLYx, children: data1?.data?.filter((child) => child.label === item.label).map((c2) => ({ ...c2, value: c2.YJLYx, name: c2.OrderType })) }; + }); + const ret1 = { + name: '预计利润', + // OrderType: 'xUpsell', + children: total1, // .sort((a, b) => a.name.localeCompare(b.name)), // .reverse(), + }; + // if(data1) console.log('🉑', ret1); + return ret1; +}; + +const _getTrainService = (arr = []) => arr.find((item) => item.OrderTypeSN === SERVICETYPE_TRAINSBOOKING) || {}; +const _getTrainUpsell = (arr = []) => arr.find((item) => item.OrderTypeSN === FORM_TRAINSUPSELL) || {}; const buildFunnelData = (data1, data2) => { // const key = 'OrderCount'; const data01 = [ - { stage: '火车票服务', number: data1?.data?.[0]?.OrderCount, dateRange: data1?.dateRangeStr }, - { stage: '成行出票', number: data1?.data?.[0]?.CJCount, dateRange: data1?.dateRangeStr }, - { stage: '火车票Upsell', number: (data1?.data?.[1]?.OrderCount || 0) + 0, dateRange: data1?.dateRangeStr }, - { stage: 'Upsell成行', number: data1?.data?.[1]?.CJCount, dateRange: data1?.dateRangeStr }, + { stage: '火车票服务', number: _getTrainService(data1?.data)?.OrderCount, dateRange: data1?.dateRangeStr }, + { stage: '成行出票', number: _getTrainService(data1?.data)?.CJCount, dateRange: data1?.dateRangeStr }, + { stage: '火车票Upsell', number: (_getTrainUpsell(data1?.data)?.OrderCount || 0) + 0, dateRange: data1?.dateRangeStr }, + { stage: 'Upsell成行', number: _getTrainUpsell(data1?.data)?.CJCount, dateRange: data1?.dateRangeStr }, ]; const data02 = !comm.isEmpty(data2) ? [ - { stage: '火车票服务', number: data2?.data?.[0]?.OrderCount, dateRange: data2?.dateRangeStr }, - { stage: '成行出票', number: data2?.data?.[0]?.CJCount, dateRange: data2?.dateRangeStr }, - { stage: '火车票Upsell', number: data2?.data?.[1]?.OrderCount, dateRange: data2?.dateRangeStr }, - { stage: 'Upsell成行', number: data2?.data?.[1]?.CJCount, dateRange: data2?.dateRangeStr }, + { stage: '火车票服务', number: _getTrainService(data2?.data)?.OrderCount || 0, dateRange: data2?.dateRangeStr }, + { stage: '成行出票', number: _getTrainService(data2?.data)?.CJCount || 0, dateRange: data2?.dateRangeStr }, + { stage: '火车票Upsell', number: _getTrainUpsell(data2?.data)?.OrderCount || 0, dateRange: data2?.dateRangeStr }, + { stage: 'Upsell成行', number: _getTrainUpsell(data2?.data)?.CJCount || 0, dateRange: data2?.dateRangeStr }, ] : []; return data01.concat(data02); @@ -96,77 +111,91 @@ const TrainsUpsell = observer(({ ...props }) => { }, }; - const pieData = buildPieData(trainsOrdersSummary); - const pieData2 = buildPieData(compareData); - // console.log('🟠', pieData, pieData2); - const pieConfig = { - appendPadding: 0, - // data: pieData, - angleField: 'number', - colorField: 'stage', - radius: 0.8, - innerRadius: 0.6, - // startAngle: Math.PI , - // endAngle: Math.PI * 1.5, - label: { - type: 'spider', - // content: '{name} {value} \n {percentage}', - content: '{name}\n{percentage}', + const sunburstData = buildSunburstData(trainsOrdersSummary, compareData); + const sunburstData2 = buildSunburstData(compareData); + const sunburstConfig = { + innerRadius: 0.3, + radius: 1, + colorField: 'name', + hierarchyConfig: { + // field: 'YJLYx', + ignoreParentValue: false, + sort: (a, b) => (a.name || '').localeCompare(b.name), }, - statistic: false, - legend: false, // 不显示图例 - interactions: [ - { - type: 'element-selected', - }, - { - type: 'element-active', - }, - ], + label: { layout: [{ type: 'limit-in-shape' }] }, + interactions: [{ type: 'element-selected' }, { type: 'element-active' }], }; + // const pieData = buildPieData(trainsOrdersSummary); + // const pieData2 = buildPieData(compareData); + // console.log('🟠', pieData, pieData2); + // const pieConfig = { + // appendPadding: 0, + // // data: pieData, + // angleField: 'number', + // colorField: 'stage', + // radius: 0.8, + // innerRadius: 0.6, + // // startAngle: Math.PI , + // // endAngle: Math.PI * 1.5, + // label: { + // type: 'spider', + // // content: '{name} {value} \n {percentage}', + // content: '{name}\n{percentage}', + // }, + // statistic: false, + // legend: false, // 不显示图例 + // interactions: [ + // { + // type: 'element-selected', + // }, + // { + // type: 'element-active', + // }, + // ], + // }; + const tableProps = { title: () => `${trainsOrdersSummary?.dateRangeStr || ''}` + (showDiff ? ` vs ${compareData?.dateRangeStr}` : ''), - dataSource: trainsOrdersSummary?.data || [], // columns: [], size: 'small', pagination: false, - scroll: { x: 100 * 7 }, + // scroll: { x: 100 * 7 }, loading, }; const tableCols = [ - { - title: '数量', - dataIndex: 'OrderCount', - render: (text, r) => (!showDiff ? text : comm.show_vs_tag(r.OrderCount_vs, r.OrderCount_diff, r.OrderCount, r.diff?.OrderCount)), - }, - { - title: '成交数', - dataIndex: 'CJCount', - render: (text, r) => (!showDiff ? text : comm.show_vs_tag(r.CJCount_vs, r.CJCount_diff, r.CJCount, r.diff?.CJCount)), - }, - { - title: '成交人数', - dataIndex: 'CJPersonNum', - render: (text, r) => (!showDiff ? text : comm.show_vs_tag(r.CJPersonNum_vs, r.CJPersonNum_diff, r.CJPersonNum, r.diff?.CJPersonNum)), - }, - { - title: '成交率', - dataIndex: 'CJrate', - render: (text, r) => (!showDiff ? text : comm.show_vs_tag(r.CJrate_vs, r.CJrate_diff, r.CJrate, r.diff?.CJrate)), - }, - { - title: '成交毛利(预计)', - dataIndex: 'YJLY', - render: (text, r) => (!showDiff ? text : comm.show_vs_tag(r.YJLY_vs, r.YJLY_diff, r.YJLY, r.diff?.YJLY)), - }, + { + title: '数量', + dataIndex: 'OrderCount', + render: (text, r) => (!showDiff ? text : comm.show_vs_tag(r.OrderCount_vs, r.OrderCount_diff, r.OrderCount, r.diff?.OrderCount)), + }, + { + title: '成交数', + dataIndex: 'CJCount', + render: (text, r) => (!showDiff ? text : comm.show_vs_tag(r.CJCount_vs, r.CJCount_diff, r.CJCount, r.diff?.CJCount)), + }, + { + title: '成交人数', + dataIndex: 'CJPersonNum', + render: (text, r) => (!showDiff ? text : comm.show_vs_tag(r.CJPersonNum_vs, r.CJPersonNum_diff, r.CJPersonNum, r.diff?.CJPersonNum)), + }, + { + title: '成交率', + dataIndex: 'CJrate', + render: (text, r) => (!showDiff ? text : comm.show_vs_tag(r.CJrate_vs, r.CJrate_diff, r.CJrate, r.diff?.CJrate)), + }, + { + title: '成交毛利(预计)', + dataIndex: 'YJLY', + render: (text, r) => (!showDiff ? text : comm.show_vs_tag(r.YJLY_vs, r.YJLY_diff, r.YJLY, r.diff?.YJLY)), + }, - { - title: '单个订单价值', - dataIndex: 'Ordervalue', - render: (text, r) => (!showDiff ? text : comm.show_vs_tag(r.Ordervalue_vs, r.Ordervalue_diff, r.Ordervalue, r.diff?.Ordervalue)), - }, - ]; + { + title: '单个订单价值', + dataIndex: 'Ordervalue', + render: (text, r) => (!showDiff ? text : comm.show_vs_tag(r.Ordervalue_vs, r.Ordervalue_diff, r.Ordervalue, r.diff?.Ordervalue)), + }, + ]; return ( <>
@@ -194,8 +223,18 @@ const TrainsUpsell = observer(({ ...props }) => { -
+
+ +
+ 火车票 @@ -205,7 +244,22 @@ const TrainsUpsell = observer(({ ...props }) => {

预计利润

- + {showDiff && ( + + )} + {/* { color={['#61DDAA', '#5B8FF9']} pattern={{ type: 'line' }} /> - )} + )} */}
@@ -238,7 +292,10 @@ const TrainsUpsell = observer(({ ...props }) => { loading={typeLoading} columns={[{ title: '#', fixed: 'left', dataIndex: 'COLI_WebCode' }, ...tableCols]} title={() => `火车票Upsell: 各站`} + rowKey={'COLI_WebCode'} /> + + {/* 外联营销 */} diff --git a/src/zustand/BizOrder.js b/src/zustand/BizOrder.js index 433a593..a683eb8 100644 --- a/src/zustand/BizOrder.js +++ b/src/zustand/BizOrder.js @@ -5,7 +5,7 @@ import { groupsMappedByCode } from '../libs/ht'; import { fetchJSON } from '../utils/request'; import { HT_HOST } from '../config'; import { resultDataCb } from '../components/DateGroupRadio/date'; -import { isEmpty } from '../utils/commons'; +import { isEmpty, price_to_number } from '../utils/commons'; const defaultParams = { WebCode: 'all', IncludeTickets: 1, IncludeInternal: 1 }; @@ -50,15 +50,15 @@ export const fetchBizOrderCountByType = async (type, params) => { OrderType: type, }); const res = errcode !== 0 ? _typeRes : (result || _typeRes); - const rows1Map = res.ordercount1.reduce((a, row1) => ({ ...a, [row1.OrderTypeSN]: row1 }), {}); - const rows2Map = res.ordercount2.reduce((a, row2) => ({ ...a, [row2.OrderTypeSN]: row2 }), {}); + const rows1Map = res.ordercount1.reduce((a, row1) => ({ ...a, [row1.OrderTypeSN]: {...row1, YJLYx: price_to_number(row1.YJLY)} }), {}); + const rows2Map = res.ordercount2.reduce((a, row2) => ({ ...a, [row2.OrderTypeSN]: {...row2, YJLYx: price_to_number(row2.YJLY)} }), {}); - const mixRow1 = res.ordercount1.map((row1) => ({ ...row1, diff: rows2Map[row1.OrderTypeSN] || {} })); + const mixRow1 = res.ordercount1.map((row1) => ({ ...row1, YJLYx: price_to_number(row1.YJLY), diff: rows2Map[row1.OrderTypeSN] || {} })); // Diff: elements in rows2 but not in rows1 const diff = [...new Set(Object.keys(rows2Map).filter((x) => !new Set(Object.keys(rows1Map)).has(x)))]; mixRow1.push(...diff.map((sn) => ({ diff: rows2Map[sn], OrderType: rows2Map[sn].OrderType, OrderTypeSN: rows2Map[sn].OrderTypeSN }))); - return { ...res, ordercount1: mixRow1 }; + return { ...res, ordercount1: mixRow1, ordercount2: res.ordercount2.map((row1) => ({ ...row1, YJLYx: price_to_number(row1.YJLY), })) }; }; const _detailRes = { ordercount1: [], ordercount2: [] }; diff --git a/src/zustand/Trains.js b/src/zustand/Trains.js index 6cbea43..70ca367 100644 --- a/src/zustand/Trains.js +++ b/src/zustand/Trains.js @@ -4,17 +4,21 @@ import { immer } from 'zustand/middleware/immer'; import { groupsCTplus, groupsMappedByCode } from '../libs/ht'; import { fetchJSON } from '../utils/request'; import { HT_HOST } from '../config'; -import { resultDataCb } from '../components/DateGroupRadio/date'; -import { fixTo2Decimals, fixTo4Decimals, groupBy, isEmpty } from '../utils/commons'; +import { fixTo2Decimals, fixTo4Decimals, groupBy, isEmpty, price_to_number } from '../utils/commons'; -const SERVICETYPE_TRAINSBOOKING = '2'; // 火车票服务 -const FORM_TRAINSBOOKING = 32024; // 火车票预定 -const FORM_TRAINSUPSELL = 32214; // 火车票Upsell +/** 火车票服务 */ +export const SERVICETYPE_TRAINSBOOKING = '2'; +/** 火车票预定 */ +export const FORM_TRAINSBOOKING = 32024; +/** 火车票Upsell */ +export const FORM_TRAINSUPSELL = 32214; +/** 外联老客户营销 */ +export const FORM_SALESSUPSELL = 32213; const defaultParams = { WebCode: 'all', IncludeTickets: 1, IncludeInternal: 1 }; const _res = { ordercount1: [], ordercount2: [] }; -export const fetchBizTrainsOrderSummaryByType = async (params, type = 'Form', typeVal = '') => { +export const fetchBizTrainsOrderSummaryByType = async (params, type = 'Form', typeVals = []) => { const { errcode, errmsg, ...result } = await fetchJSON(HT_HOST + '/service-web/QueryData/GetOrderCountByType_biz', { ...defaultParams, ...params, @@ -27,20 +31,36 @@ export const fetchBizTrainsOrderSummaryByType = async (params, type = 'Form', ty const res = errcode !== 0 ? _res : result || _res; const dateStr = [params.Date1, params.Date2].map((d) => d.substring(0, 10)).join('~'); const ret = [ - { dateRangeStr: dateStr, data: res.ordercount1.find((row) => row.OrderTypeSN === typeVal) }, + { + dateRangeStr: dateStr, + data: res.ordercount1.filter((row) => typeVals.includes(row.OrderTypeSN)).map((row) => ({ ...row, YJLYx: price_to_number(row.YJLY), label: '商务' })), + total: { ...res.ordercountTotal1, YJLYx: price_to_number(res.ordercountTotal1.YJLY), label: '商务' }, + type, + }, // { dateRangeStr: dateDiffStr, data: res.ordercount2.find((row) => row.OrderTypeSN === typeVal) }, ]; const dateDiffStr = isEmpty(params.DateDiff1) ? '' : [params.DateDiff1, params.DateDiff2].map((d) => d.substring(0, 10)).join('~'); if (!isEmpty(dateDiffStr)) { - ret.push({ dateRangeStr: dateDiffStr, data: res.ordercount2.find((row) => row.OrderTypeSN === typeVal) }); + ret[0].total.diff = { ...res.ordercountTotal2, YJLYx: price_to_number(res.ordercountTotal2.YJLY) }; + ret[0].data.forEach((row) => { + const _find = res.ordercount2.find((row2) => row2.OrderTypeSN === row.OrderTypeSN) || {}; + row.diff = { ..._find, YJLYx: price_to_number(_find.YJLY || 0) }; + }); + ret.push({ + dateRangeStr: dateDiffStr, + data: res.ordercount2.filter((row) => typeVals.includes(row.OrderTypeSN)).map((row) => ({ ...row, YJLYx: price_to_number(row.YJLY), label: '商务' })), + total: { ...res.ordercountTotal2, YJLYx: price_to_number(res.ordercountTotal2.YJLY), label: '商务' }, + type, + }); } + // console.log('😉', ret); return ret; }; /** * 从传统订单中获取upsell数据 */ -export const fetchTrainsUpsellTSummaryByType = async (params, type = 'Form', typeVal = '') => { +export const fetchTrainsUpsellTSummaryByType = async (params, type = 'Form', typeVals = []) => { const { errcode, errmsg, ...result } = await fetchJSON(HT_HOST + '/service-web/QueryData/GetOrderCountByType', { ...defaultParams, ...params, @@ -53,13 +73,29 @@ export const fetchTrainsUpsellTSummaryByType = async (params, type = 'Form', typ const res = errcode !== 0 ? _res : result || _res; const dateStr = [params.Date1, params.Date2].map((d) => d.substring(0, 10)).join('~'); const ret = [ - { dateRangeStr: dateStr, data: res.ordercount1.find((row) => row.OrderTypeSN === typeVal) }, + { + dateRangeStr: dateStr, + data: res.ordercount1.filter((row) => typeVals.includes(row.OrderTypeSN)).map(row => ({...row, YJLYx: price_to_number(row.YJLY), label: '传统'})), + total: { ...res.ordercountTotal1, YJLYx: price_to_number(res.ordercountTotal1.YJLY), label: '传统' }, + type, + }, // { dateRangeStr: dateDiffStr, data: res.ordercount2.find((row) => row.OrderTypeSN === typeVal) }, ]; const dateDiffStr = isEmpty(params.DateDiff1) ? '' : [params.DateDiff1, params.DateDiff2].map((d) => d.substring(0, 10)).join('~'); if (!isEmpty(dateDiffStr)) { - ret.push({ dateRangeStr: dateDiffStr, data: res.ordercount2.find((row) => row.OrderTypeSN === typeVal) }); + ret[0].total.diff = { ...res.ordercountTotal2, YJLYx: price_to_number(res.ordercountTotal2.YJLY) }; + ret[0].data.forEach((row) => { + const _find = res.ordercount2.find((row2) => row2.OrderTypeSN === row.OrderTypeSN) || {}; + row.diff = { ..._find, YJLYx: price_to_number(_find.YJLY || 0) }; + }); + ret.push({ + dateRangeStr: dateDiffStr, + data: res.ordercount2.filter((row) => typeVals.includes(row.OrderTypeSN)).map(row => ({...row, YJLYx: price_to_number(row.YJLY), label: '传统'})), + total: { ...res.ordercountTotal2, YJLYx: price_to_number(res.ordercountTotal2.YJLY), label: '传统' }, + type, + }); } + // console.log('😉😉', ret); return ret; }; @@ -83,10 +119,10 @@ const calcSummary = (arr, keepKeys = []) => { }; const _detailRes = { ordercount1: [], ordercount2: [] }; -export const fetchUpsellOrderDetailByType = async (params, type = 'Form', typeVal = FORM_TRAINSUPSELL, orderContent = 'detail') => { +export const fetchUpsellOrderDetailByType = async (params, type = 'Form', typeVal = FORM_TRAINSUPSELL) => { const { errcode, errmsg, ...result } = await fetchJSON(HT_HOST + '/service-web/QueryData/GetOrderCountByType_Sub', { ...defaultParams, - SubOrderType: orderContent, + SubOrderType: 'detail', ...params, COLI_ApplyDate1: params.Date1, COLI_ApplyDate2: params.Date2, @@ -114,8 +150,8 @@ export const fetchUpsellOrderDetailByType = async (params, type = 'Form', typeVa if (!isEmpty(dateDiffStr)) { const [{ byWebCode: byWebCode1 }, { byWebCode: byWebCode2 }] = retS; const withDiff1 = byWebCode1.map((row, i) => { - const row2 = byWebCode2.find((r2) => r2.COLI_WebCode === row.COLI_WebCode); - row.diff = row2 || {}; + const row2 = (byWebCode2.find((r2) => r2.COLI_WebCode === row.COLI_WebCode)) || {}; + row.diff = row2; row.CJCount_vs = row2.CJCount ? fixTo2Decimals(((row.CJCount - row2.CJCount) / row2.CJCount) * 100) : 0; row.CJPersonNum_vs = row2.CJPersonNum ? fixTo2Decimals(((row.CJPersonNum - row2.CJPersonNum) / row2.CJPersonNum) * 100) : 0; row.CJrate_vs = row2.CJrate ? fixTo2Decimals(row.CJrate - row2.CJrate) : 0; @@ -156,6 +192,9 @@ export const fetchUpsellOrderDetailByType = async (params, type = 'Form', typeVa retS.forEach(({ summary, byWebCode }, i) => { summary.CJrate = `${summary.CJrate}%`; if (i !== 0) { + byWebCode.forEach((row) => { + row.CJrate = `${row.CJrate}%`; + }); } else { byWebCode.forEach((row) => { row.CJrate = `${row.CJrate}%`; @@ -172,37 +211,33 @@ export const fetchUpsellOrderDetailByType = async (params, type = 'Form', typeVa }; export const fetchTrainsWithUpsellSummary = async (params) => { - const [trains, upsell] = await Promise.all([ - // fetchBizTrainsOrderSummaryByType(params, 'Form', FORM_TRAINSBOOKING), // todo: 换成servicetype=2 - fetchBizTrainsOrderSummaryByType(params, 'servicetype', SERVICETYPE_TRAINSBOOKING), - fetchTrainsUpsellTSummaryByType(params, 'Form', FORM_TRAINSUPSELL), + const [bizForm, bizService, upsell] = await Promise.all([ + fetchBizTrainsOrderSummaryByType(params, 'Form', [FORM_TRAINSBOOKING]), + fetchBizTrainsOrderSummaryByType(params, 'servicetype', [SERVICETYPE_TRAINSBOOKING]), + fetchTrainsUpsellTSummaryByType(params, 'Form', [FORM_TRAINSUPSELL, FORM_SALESSUPSELL]), ]); - if (!isEmpty(trains[1])) { - trains[0].data.diff = trains[1].data; - upsell[0].data.diff = upsell[1].data; - } - const mergedMap = [...trains, ...upsell].reduce((acc, currentItem, currentIndex) => { - const dateRange = currentItem.dateRangeStr; + // console.log('🟠','\n', structuredClone(bizForm), '\n', structuredClone(bizService),'\n', structuredClone(upsell)); + const bizTotalOnly = structuredClone(bizForm).map((item) => ({ ...item, data: [] })); + const bizServiceDataOnly = structuredClone(bizService).map((item) => ({ ...item, total: {} })); + // console.log('🟠',bizTotalOnly, '\n', '\n', bizServiceDataOnly,'\n', upsell); + const mapByDate = new Map(); + for (const item of [...bizTotalOnly, ...bizServiceDataOnly, ...upsell]) { + const dateRange = item.dateRangeStr; - if (acc[dateRange]) { - acc[dateRange].data.push(currentItem.data); - - for (const key in currentItem) { - if (key !== 'dateRange' && key !== 'data') { - acc[dateRange][key] = currentItem[key]; - } - } + if (mapByDate.has(dateRange)) { + const existingItem = mapByDate.get(dateRange); + if (!isEmpty(item.total)) existingItem.total.push(item.total); + existingItem.data.push(...item.data); } else { - acc[dateRange] = { - ...currentItem, - data: [currentItem.data], - }; + mapByDate.set(dateRange, { + ...item, + data: item.data, + total: [item.total], + }); } - - return acc; - }, {}); - return Object.values(mergedMap); - // return groupBy([...trains, ...upsell], 'dateRangeStr'); + } + // console.log('🔰0', Array.from(mapByDate.values())); + return Array.from(mapByDate.values()); }; /**