feat: GH 市场例会数据

feature/hotel-cruise
Lei OT 1 year ago
parent fe29cb3d1c
commit 81ee6594c0

@ -45,6 +45,7 @@ import Detail from './views/Detail';
import ServicePersonNum from './views/ServicePersonNum'; import ServicePersonNum from './views/ServicePersonNum';
import DataPivot from './views/DataPivot'; import DataPivot from './views/DataPivot';
import Welcome from './views/Welcome'; import Welcome from './views/Welcome';
import Meeting2024GH from './views/Meeting2024-GH';
import { stores_Context, APP_VERSION } from './config'; import { stores_Context, APP_VERSION } from './config';
import { WaterMark } from '@ant-design/pro-components'; import { WaterMark } from '@ant-design/pro-components';
@ -75,7 +76,10 @@ const App = () => {
{ {
key: 'orders-pivot', key: 'orders-pivot',
label: <NavLink to="/orders/pivot">数据透视</NavLink>, label: <NavLink to="/orders/pivot">数据透视</NavLink>,
// icon: <DashboardOutlined />, },
{
key: 'meeting-2024-GH',
label: <NavLink to="/orders/meeting-2024-GH">例会数据2024-GH</NavLink>,
}, },
], ],
}, },
@ -208,6 +212,7 @@ const App = () => {
<Route path="/orders_sub/:ordertype/:ordertype_sub/:ordertype_title" element={<Orders_sub />} /> <Route path="/orders_sub/:ordertype/:ordertype_sub/:ordertype_title" element={<Orders_sub />} />
<Route path="/dashboard" element={<Dashboard />} /> <Route path="/dashboard" element={<Dashboard />} />
<Route path="/:page/pivot" element={<DataPivot />} /> <Route path="/:page/pivot" element={<DataPivot />} />
<Route path="/orders/meeting-2024-GH" element={<Meeting2024GH />} />
</Route> </Route>
<Route element={<ProtectedRoute auth={['admin', 'director_bu', 'customer_care']} />}> <Route element={<ProtectedRoute auth={['admin', 'director_bu', 'customer_care']} />}>
<Route path="/customer_care_inchina" element={<Customer_care_inchina />} /> <Route path="/customer_care_inchina" element={<Customer_care_inchina />} />

@ -15,6 +15,7 @@ import KPI from "./KPI";
import DictData from "./DictData"; import DictData from "./DictData";
import Distribution from "./Distribution"; import Distribution from "./Distribution";
import DataPivot from './DataPivot'; import DataPivot from './DataPivot';
import MeetingData from './MeetingData';
class Index { class Index {
constructor() { constructor() {
this.dashboard_store = new DashboardStore(this); this.dashboard_store = new DashboardStore(this);
@ -33,6 +34,7 @@ class Index {
this.DictDataStore = new DictData(this); this.DictDataStore = new DictData(this);
this.DistributionStore = new Distribution(this); this.DistributionStore = new Distribution(this);
this.DataPivotStore = new DataPivot(this); this.DataPivotStore = new DataPivot(this);
this.MeetingDataStore = new MeetingData(this);
makeAutoObservable(this); makeAutoObservable(this);
} }

@ -0,0 +1,149 @@
import { makeAutoObservable, runInAction } from 'mobx';
import { fetchJSON } from '../utils/request';
import { objectMapper } from '../utils/commons';
import { pivotBy } from './../libs/ht';
/**
* 用于透视的数据
*/
const getDetailData = async (param) => {
const json = await fetchJSON('/service-Analyse2/GetTradeApartDetail', param);
return json.errcode === 0 ? json.result : [];
};
/**
*
*/
const getOrderCountByType = async (param) => {
const paramBody = objectMapper(param, {
WebCode: 'WebCode',
OrderType: 'OrderType',
IncludeTickets: 'IncludeTickets',
DateType: 'DateType',
DepartmentList: 'DepartmentList', // { key: 'DepartmentList', transform: (v) => v.join(',') },
Date1: 'COLI_ApplyDate1',
Date2: 'COLI_ApplyDate2',
});
const url = '/service-web/QueryData/GetOrderCountByType';
const json = await fetchJSON(url, paramBody);
return json.errcode === 0 ? json : {};
};
const GHproductTypeListSetting = {
ja: ['日本', '东亚跨国'],
se: ['东南亚跨国', '泰国', '越南', '印度尼西亚', '水灯节'],
in: ['印度', '次大陆跨国', '尼泊尔', '不丹', '斯里兰卡'],
};
const rowItem = (filterData) => {
const { data: dataByLineClass, summaryMix: summaryByLineClass } = pivotBy(filterData, [['COLI_LineClass'], [], []]);
const LineClass_Origin = dataByLineClass.filter((ele) => ele.COLI_LineClass.toLocaleLowerCase().indexOf('网前自然订单') !== -1).reduce((r, c) => r + c.SumOrder, 0);
const LineClass_PPC = dataByLineClass.filter((ele) => ele.COLI_LineClass.toLocaleLowerCase().indexOf('ppc') !== -1).reduce((r, c) => r + c.SumOrder, 0);
const { data: dataByWebCode, summaryMix: summaryByWebCode } = pivotBy(filterData, [['WebCode'], [], []]);
const toB = dataByWebCode.filter((ele) => ele.WebCode.toLocaleLowerCase().indexOf('to b') !== -1).reduce((r, c) => r + c.SumOrder, 0);
const { data: dataByIsOld, summaryMix: summaryByIsOld } = pivotBy(filterData, [['IsOld', 'isCusCommend'], [], []]);
const isOld1 = dataByIsOld.filter((ele) => ele.rowLabel.indexOf('1') !== -1).reduce((r, c) => r + c.SumOrder, 0);
const total = LineClass_Origin + LineClass_PPC + toB + isOld1;
return { LineClass_Origin, LineClass_PPC, toB, isOld1, total };
};
// 日本+: 日本+东亚跨国
const dataJA = (rawData, yearData) => {
const productTypeList = GHproductTypeListSetting.ja;
const filterData = rawData.filter((ele) => productTypeList.some((item) => ele.productType.toLocaleLowerCase().indexOf(item) !== -1));
const filterDataYear = yearData.filter((ele) => productTypeList.some((item) => ele.OrderType.toLocaleLowerCase().indexOf(item) !== -1));
const rowYear = filterDataYear.reduce((r, c) => r + c.OrderCount, 0);
return { ...rowItem(filterData), rowYear };
};
// 东南亚+: 东南亚跨国+泰国+越南+印尼+水灯节线路
const dataSE = (rawData, yearData) => {
const productTypeList = GHproductTypeListSetting.se;
const filterData = rawData.filter((ele) => productTypeList.some((item) => ele.productType.toLocaleLowerCase().indexOf(item) !== -1));
const filterDataYear = yearData.filter((ele) => productTypeList.some((item) => ele.OrderType.toLocaleLowerCase().indexOf(item) !== -1));
const rowYear = filterDataYear.reduce((r, c) => r + c.OrderCount, 0);
return { ...rowItem(filterData), rowYear };
};
// 印度+: 印度+次大陆跨国+尼泊尔+不丹+斯里兰卡
const dataIN = (rawData, yearData) => {
const productTypeList = GHproductTypeListSetting.in;
const filterData = rawData.filter((ele) => productTypeList.some((item) => ele.productType.toLocaleLowerCase().indexOf(item) !== -1));
const filterDataYear = yearData.filter((ele) => productTypeList.some((item) => ele.OrderType.toLocaleLowerCase().indexOf(item) !== -1));
const rowYear = filterDataYear.reduce((r, c) => r + c.OrderCount, 0);
return { ...rowItem(filterData), rowYear };
};
// 其他GH
const dataGHOther = (rawData, yearData) => {
const exceptProduct = Object.values(GHproductTypeListSetting).reduce((r, c) => r.concat(c), []);
const filterData = rawData.filter((ele) => exceptProduct.every((item) => ele.productType.toLocaleLowerCase().indexOf(item) === -1));
const filterDataYear = yearData.filter((ele) => exceptProduct.every((item) => ele.OrderType.toLocaleLowerCase().indexOf(item) === -1));
const rowYear = filterDataYear.reduce((r, c) => r + c.OrderCount, 0);
return { ...rowItem(filterData), rowYear };
};
class MeetingData {
constructor(rootStore) {
this.rootStore = rootStore;
makeAutoObservable(this);
}
searchValues = {
DateType: { key: 'applyDate', value: 'applyDate', label: '提交日期' },
};
setSearchValues(body) {
this.searchValues = body;
}
GHTableData = [];
GHLoading = false;
dataGH = async (param) => {
// console.log('dataGH', param);
this.GHLoading = true;
// 本周
const CHData = await getDetailData({ ...param, 'DepartmentList': '1', 'WebCode': 'All' });
const exceptCHData = await getDetailData({ ...param, 'DepartmentList': '28,33', 'WebCode': 'All' });
/** 截至今年 - 行 */
const { ordercountTotal1: CHDataYear } = await getOrderCountByType({ ...param, Date1: '2024-01-01', 'DepartmentList': '1', 'WebCode': 'All', OrderType: 'LineClass' });
const { ordercount1: exceptCHDataYear } = await getOrderCountByType({ ...param, Date1: '2024-01-01', 'DepartmentList': '28,33', 'WebCode': 'All', OrderType: 'Product' });
/** 截至今年 - 列 */
const { ordercount1: ColLineClassDataYear } = await getOrderCountByType({ ...param, Date1: '2024-01-01', 'DepartmentList': '1,2,28,7,33', 'WebCode': 'All', OrderType: 'LineClass' });
const { ordercountTotal1: ColToBDataYear } = await getOrderCountByType({ ...param, Date1: '2024-01-01', 'DepartmentList': '1,2,28,7,33', 'WebCode': 'GHTOBHW,GHTOBZG', OrderType: 'LineClass' });
// 老客户
const yearDetail = await getDetailData({ ...param, Date1: '2024-01-01', 'DepartmentList': '1,2,28,7,33', 'WebCode': 'All' });
const { isOld1: isOld1Year } = rowItem(yearDetail);
const colYearRow = {
LineClass_Origin: ColLineClassDataYear.filter((ele) => ele.OrderType.toLocaleLowerCase().indexOf('网前自然订单') !== -1).reduce((r, c) => r + c.OrderCount, 0),
LineClass_PPC: ColLineClassDataYear.filter((ele) => ele.OrderType.toLocaleLowerCase().indexOf('ppc') !== -1).reduce((r, c) => r + c.OrderCount, 0),
toB: ColToBDataYear.OrderCount,
isOld1: isOld1Year,
};
const rows = [
{ key: 'ch', label: '中国', ...rowItem(CHData), rowYear: CHDataYear.OrderCount },
{ key: 'ja', label: '日本+', ...dataJA(exceptCHData, exceptCHDataYear) },
{ key: 'se', label: '东南亚+', ...dataSE(exceptCHData, exceptCHDataYear) },
{ key: 'in', label: '印度+', ...dataIN(exceptCHData, exceptCHDataYear) },
{ key: 'other', label: '其他GH', ...dataGHOther(exceptCHData, exceptCHDataYear) },
];
const columnsSum = ['LineClass_Origin', 'LineClass_PPC', 'toB', 'isOld1', 'total', 'rowYear'].reduce(
(r, col) => ({
...r,
[col]: rows.reduce((rr, row) => rr + row[col], 0),
}),
{}
);
rows.push({ key: 'columnSum', label: '合计', ...columnsSum });
rows.push({ key: 'colYearRow', label: '截至', ...colYearRow });
// console.log(rows);
runInAction(() => {
this.GHTableData = rows;
this.GHLoading = false;
});
};
}
export default MeetingData;

@ -481,6 +481,7 @@ export function objectMapper(input, keyMap) {
if (map) { if (map) {
let value = input[key]; let value = input[key];
if (map.transform) value = map.transform(value); if (map.transform) value = map.transform(value);
if (typeof map === 'string') mappedObj[map] = value;
mappedObj[map.key || key] = value; mappedObj[map.key || key] = value;
} }
} }

@ -0,0 +1,74 @@
import { useContext } from 'react';
import { observer } from 'mobx-react';
import { stores_Context } from '../config';
import { Table, Row, Col, Divider } from 'antd';
import SearchForm from '../components/search/SearchForm';
import { TableExportBtn } from './../components/Data';
// TdCellDataTable
const TdCell = (tdprops) => {
// onMouseEnter, onMouseLeave
const { onMouseEnter, onMouseLeave, ...restProps } = tdprops;
return <td {...restProps} />;
};
export default observer((props) => {
const { date_picker_store: searchFormStore, MeetingDataStore } = useContext(stores_Context);
const { formValues, formValuesToSub, siderBroken } = searchFormStore;
const dataRefresh = async (obj) => {
await MeetingDataStore.dataGH({
...(obj || formValuesToSub),
});
};
const targetTableProps = {
loading: MeetingDataStore.GHLoading,
// sticky: true,
scroll: { x: 1000, y: 400 },
pagination: false,
columns: [
{ key: 'label', title: '', dataIndex: 'label' },
{ key: 'LineClass_Origin', title: '网站', dataIndex: 'LineClass_Origin' },
{ key: 'LineClass_PPC', title: 'PPC', dataIndex: 'LineClass_PPC' },
{ key: 'toB', title: 'To B', dataIndex: 'toB' },
{ key: 'isOld1', title: '老客户', dataIndex: 'isOld1' },
{ key: 'total', title: '合计', dataIndex: 'total' },
{ key: 'rowYear', title: '截至年订单数', dataIndex: 'rowYear' },
// { key: 'groupsLabel2', title: '', dataIndex: 'groupsLabel2' },
// { key: 'groupsLabel2', title: '', dataIndex: 'groupsLabel2' },
],
};
return (
<>
<Row gutter={16} className={siderBroken ? '' : 'sticky-top'}>
<Col className="gutter-row" span={24}>
<SearchForm
defaultValue={{
initialValue: {
...formValues,
...MeetingDataStore.searchValues,
// ...searchInitial,
},
shows: ['DateType', 'IncludeTickets', 'dates'], // 'country'
fieldProps: {
dates: { hide_vs: true },
},
}}
onSubmit={(_err, obj, form, str) => {
MeetingDataStore.setSearchValues(form);
dataRefresh(obj);
}}
/>
</Col>
</Row>
<Divider orientation="right" plain>
<span>2024-GH</span>
<TableExportBtn label={formValuesToSub.Date1} {...{ columns: targetTableProps.columns, dataSource: MeetingDataStore.GHTableData }} />
</Divider>
<Table {...targetTableProps} dataSource={MeetingDataStore.GHTableData} components={{ body: { cell: TdCell } }} />
</>
);
});
Loading…
Cancel
Save