feat: GH例会数据, 2025模板

feature/hotel-cruise
Lei OT 5 months ago
parent b2ce88e8aa
commit a0b71dba79

@ -14,7 +14,7 @@ import {
FlagOutlined, FlagOutlined,
PieChartOutlined, PieChartOutlined,
BarChartOutlined, BarChartOutlined,
CoffeeOutlined, CoffeeOutlined, DesktopOutlined
} from '@ant-design/icons'; } from '@ant-design/icons';
import { Layout, Menu, Image, Badge, Button } from 'antd'; import { Layout, Menu, Image, Badge, Button } from 'antd';
import { BrowserRouter, Route, Routes, NavLink } from 'react-router-dom'; import { BrowserRouter, Route, Routes, NavLink } from 'react-router-dom';
@ -46,6 +46,7 @@ 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 Meeting2024GH from './views/Meeting2024-GH';
import Meeting2025GH from './views/Meeting2025-GH';
import SalesCustomerCareRegular from './views/SalesCustomerCareRegular'; import SalesCustomerCareRegular from './views/SalesCustomerCareRegular';
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';
@ -58,7 +59,22 @@ const App = () => {
const menu_items = [ const menu_items = [
{ key: 1, label: <NavLink to="/">欢迎</NavLink>, icon: <CoffeeOutlined /> }, { key: 1, label: <NavLink to="/">欢迎</NavLink>, icon: <CoffeeOutlined /> },
{ key: 'annual', label: <NavLink to="/annual">综合看板</NavLink>, icon: <DashboardOutlined /> }, { key: 'annual', label: <NavLink to="/annual">综合年度</NavLink>, icon: <DashboardOutlined /> },
{
key: 'mixed',
label: '报告',
icon: <DesktopOutlined />,
children: [
{
key: 'meeting-2025-GH',
label: <NavLink to="/orders/meeting-2025-GH">GH例会数据-2025</NavLink>, // GH-2024
},
{
key: 'meeting-2024-GH',
label: <NavLink to="/orders/meeting-2024-GH">GH区域数据</NavLink>, // GH-2024
},
]
},
{ {
key: 2, key: 2,
label: '市场', label: '市场',
@ -78,10 +94,6 @@ const App = () => {
key: 'orders-pivot', key: 'orders-pivot',
label: <NavLink to="/orders/pivot">数据透视</NavLink>, label: <NavLink to="/orders/pivot">数据透视</NavLink>,
}, },
{
key: 'meeting-2024-GH',
label: <NavLink to="/orders/meeting-2024-GH">例会数据2024-GH</NavLink>,
},
], ],
}, },
{ {
@ -218,6 +230,7 @@ const App = () => {
<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 path="/orders/meeting-2024-GH" element={<Meeting2024GH />} />
<Route path="/orders/meeting-2025-GH" element={<Meeting2025GH />} />
</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 />} />

@ -81,7 +81,7 @@ export const TableExportBtn = (props) => {
}; };
return ( return (
<Button <Button {...props}
type="link" type="link"
icon={<DownloadOutlined />} icon={<DownloadOutlined />}
size="small" size="small"

@ -67,6 +67,7 @@ export const sites = [
{ value: '2', key: '2', label: 'CHT', code: 'CHT' }, { value: '2', key: '2', label: 'CHT', code: 'CHT' },
{ value: '8', key: '8', label: 'AH', code: 'AH' }, { value: '8', key: '8', label: 'AH', code: 'AH' },
{ value: '163', key: '163', label: 'GH', code: 'GH' }, { value: '163', key: '163', label: 'GH', code: 'GH' },
{ value: '184', key: '184', label: '站外渠道', code: 'ZWQD' },
{ value: '28', key: '28', label: '客运中国', code: 'GHKYZG' }, { value: '28', key: '28', label: '客运中国', code: 'GHKYZG' },
{ value: '7', key: '7', label: '客运海外', code: 'GHKYHW' }, { value: '7', key: '7', label: '客运海外', code: 'GHKYHW' },
{ value: '172', key: '172', label: 'GHToB 海外', code: 'GHTOBHW' }, { value: '172', key: '172', label: 'GHToB 海外', code: 'GHTOBHW' },
@ -74,7 +75,6 @@ export const sites = [
{ value: '11,12,20,21,10,18', key: '11,12,20,21,10,18', label: '国际(入境)', code: 'JP,VAC,IT,GM,RU,VC' }, { value: '11,12,20,21,10,18', key: '11,12,20,21,10,18', label: '国际(入境)', code: 'JP,VAC,IT,GM,RU,VC' },
{ value: '122,200,211,100,188', key: '122,200,211,100,188', label: '国际(海外)', code: 'VACHW,ITHW,GMHW,RUHW,VCHW' }, { value: '122,200,211,100,188', key: '122,200,211,100,188', label: '国际(海外)', code: 'VACHW,ITHW,GMHW,RUHW,VCHW' },
{ value: '178,179,180,181,182,183', key: '178,179,180,181,182,183', label: '国际GH', code: 'gh_gm,gh_jp,gh_vc,gh_vac,gh_ru,gh_it'}, { value: '178,179,180,181,182,183', key: '178,179,180,181,182,183', label: '国际GH', code: 'gh_gm,gh_jp,gh_vc,gh_vac,gh_ru,gh_it'},
{ value: '184', key: '184', label: '站外渠道', code: 'ZWQD' },
{ value: '11', key: '11', label: '日语', code: 'JP' }, { value: '11', key: '11', label: '日语', code: 'JP' },
{ value: '179', key: '179', label: 'GH-日语', code: 'gh_jp'}, // www.globalhighlights.jp { value: '179', key: '179', label: 'GH-日语', code: 'gh_jp'}, // www.globalhighlights.jp
{ value: '12', key: '12', label: '西语', code: 'VAC' }, { value: '12', key: '12', label: '西语', code: 'VAC' },

@ -15,7 +15,8 @@ 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'; import MeetingData from './MeetingData2024';
import MeetingData2025 from './MeetingData2025';
class Index { class Index {
constructor() { constructor() {
this.dashboard_store = new DashboardStore(this); this.dashboard_store = new DashboardStore(this);
@ -35,6 +36,7 @@ class Index {
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); this.MeetingDataStore = new MeetingData(this);
this.MeetingData2025Store = new MeetingData2025(this);
makeAutoObservable(this); makeAutoObservable(this);
} }

@ -1,7 +1,7 @@
import { makeAutoObservable, runInAction } from 'mobx'; import { makeAutoObservable, runInAction } from 'mobx';
import { fetchJSON } from '../utils/request'; import { fetchJSON } from '../utils/request';
import { objectMapper, pick, price_to_number, } from '../utils/commons'; import { objectMapper, pick, price_to_number, } from '../utils/commons';
import { pivotBy } from './../libs/ht'; import { pivotBy } from '../libs/ht';
import moment from "moment"; import moment from "moment";
import { DATE_FORMAT, DATETIME_FORMAT, SMALL_DATETIME_FORMAT } from '../config'; import { DATE_FORMAT, DATETIME_FORMAT, SMALL_DATETIME_FORMAT } from '../config';

@ -0,0 +1,474 @@
import { makeAutoObservable, runInAction } from 'mobx';
import { fetchJSON } from '../utils/request';
import { objectMapper, pick, price_to_number, } from '../utils/commons';
import { pivotBy } from './../libs/ht';
import moment from "moment";
import { DATE_FORMAT, DATETIME_FORMAT, SMALL_DATETIME_FORMAT } from '../config';
/**
* 用于透视的数据
*/
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 getAgentGroupInfoALL = async (param) => {
const paramBody = objectMapper(param, {
DateType: 'DateType',
DepartmentList: 'DepList', // { key: 'DepartmentList', transform: (v) => v.join(',') },
Date1: 'OldDate1',
Date2: 'OldDate2',
});
const url = '/service-web/QueryData/GetAgentGroupInfoALL';
const json = await fetchJSON(url, paramBody);
return json.errcode === 0 ? json : {};
};
const getDepartmentOrderMLByType = async (param) => {
const paramBody = objectMapper(param, {
DateType: 'DateType',
DepartmentList: 'DepartmentList', // { key: 'DepartmentList', transform: (v) => v.join(',') },
OrderType: 'OrderType', // 总览, 产品类型
});
const url = '/service-web/QueryData/GetDepartmentOrderMLByType';
const json = await fetchJSON(url, paramBody);
const { result1 } = json.errcode === 0 ? json : { result1: [] };
const total1 = ['COLI_CJCount', 'COLI_ML2',].reduce(
(r, col) => ({
...r,
[col]: result1.reduce((rr, row) => rr + row[col], 0),
}),
{}
);
return { total1, result1 };
};
const GHproductTypeListSetting = {
ja: ['日本', '东亚跨国'],
se: ['东南亚跨国', '泰国', '越南', '印度尼西亚', '水灯节', '柬埔寨', '老挝'],
in: ['印度', '印度次大陆跨国', '尼泊尔', '不丹', '斯里兰卡'],
};
const GHCountryListSetting = {
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 external = dataByWebCode.filter((ele) => ele.WebCode.toLocaleLowerCase().indexOf("站外渠道") !== -1).reduce((r, c) => r + c.SumOrder, 0);
const filterIsOldC = filterData.filter((ele) => ele.WebCode.toLocaleLowerCase().indexOf('to b') === -1);
const { data: dataByIsOld, summaryMix: summaryByIsOld } = pivotBy(filterIsOldC, [['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 + external;
return { LineClass_Origin, LineClass_PPC, toB, external, 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 exceptProduct = ['印度尼西亚'];
const filterData = rawData
.filter((ele) => productTypeList.some((item) => ele.productType.toLocaleLowerCase().indexOf(item) !== -1))
.filter((ele) => exceptProduct.every((item) => ele.productType.toLocaleLowerCase().indexOf(item) === -1));
const filterDataYear = yearData
.filter((ele) => productTypeList.some((item) => ele.OrderType.toLocaleLowerCase().indexOf(item) !== -1))
.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 };
};
// 其他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 };
};
const dataSales = (tKey, rawData, yearData, yearData2) => {
const targetList = GHCountryListSetting[tKey];
const tIndex = Object.keys(GHCountryListSetting).indexOf(tKey);
const exceptTargetList = Object.keys(GHCountryListSetting).reduce((r, c, i) => r.concat(i < tIndex ? GHCountryListSetting[c] : []), []);
// console.log(tIndex, tKey, 'exceptTargetList', exceptTargetList, 'targetList', targetList);
const filterRaw1 = rawData.filter((ele) => exceptTargetList.every((item) => !ele.destinationCountry_AsJOSN.includes(item)));
// console.log(tKey, 'filterRaw1', filterRaw1);
const filterDataC = filterRaw1.filter((ele) => targetList.some((item) => ele.destinationCountry_AsJOSN.includes(item)));
const filterDataT = tKey === 'se' ? filterRaw1.filter((ele) => ['泰国水灯节'].some((item) => ele.productType.toLocaleLowerCase().indexOf(item) !== -1)) : [];
const filterData = filterDataC.concat(filterDataT);
const CJCount = filterData.length; // filterData.reduce((r, c) => r + c.CJCount, 0);
const YJLY = filterData.reduce((r, c) => r + price_to_number(c.ML), 0);
const filterRaw2 = yearData.filter((ele) => exceptTargetList.every((item) => !ele.destinationCountry_AsJOSN.includes(item)));
const filterDataYearC = filterRaw2.filter((ele) => targetList.some((item) => ele.destinationCountry_AsJOSN.includes(item)));
const filterDataYearT = tKey === 'se' ? filterRaw2.filter((ele) => ['泰国水灯节'].some((item) => ele.productType.toLocaleLowerCase().indexOf(item) !== -1)) : [];
const filterDataYear = filterDataYearC.concat(filterDataYearT);
const rowYearData = { CJCount: filterDataYear.length, YJLY: filterDataYear.reduce((r, c) => r + price_to_number(c.ML), 0) };
// console.log(tKey, filterDataYear.map(ee => ee.destinationCountry_AsJOSN), filterDataYear.map(ee => ee.productType), filterDataYear);
const filterDataYearRaw2 = yearData2.filter((ele) => exceptTargetList.every((item) => !ele.destinationCountry_AsJOSN.includes(item)));
const filterDataYear2C = filterDataYearRaw2.filter((ele) => targetList.some((item) => ele.destinationCountry_AsJOSN.includes(item)));
const filterDataYear2T = tKey === 'se' ? filterDataYearRaw2.filter((ele) => ['泰国水灯节'].some((item) => ele.productType.toLocaleLowerCase().indexOf(item) !== -1)) : [];
const filterDataYear2 = filterDataYear2C.concat(filterDataYear2T);
const rowYearData2 = { CJCount: filterDataYear2.length, YJLY: filterDataYear2.reduce((r, c) => r + price_to_number(c.ML), 0) };
const rowYear = {
YJLY: price_to_number(rowYearData.YJLY), CJCount: rowYearData.CJCount, GroupCount: rowYearData.CJCount,
YJLY2: price_to_number(rowYearData2.YJLY), CJCount2: rowYearData2.CJCount, GroupCount2: rowYearData2.CJCount,
};
const cols = ['YJLY', 'CJCount'].reduce((r, key) => ({ ...r, [key]: filterData.reduce((a, c) => a + price_to_number(c[key]), 0) }), {});
// console.log(tKey, filterData, filterDataYear, filterDataYear2);
return { ...cols, GroupCount:CJCount, CJCount, YJLY, rowYear, rawData: filterData, rawYearData: filterDataYear, rawYearData2: filterDataYear2 };
};
const dataSalesGHOther = (rawData, yearData, yearData2) => {
const exceptContry = Object.values(GHCountryListSetting).reduce((r, c) => r.concat(c), []);
// console.log('exceptContry', exceptContry);
// console.log('OOoo rawData', rawData.map(e => e.destinationCountry_AsJOSN));
const filterData = rawData
.filter((ele) => ['泰国水灯节'].every((item) => ele.productType.toLocaleLowerCase().indexOf(item) === -1))
.filter((ele) => exceptContry.every((item) => !ele.destinationCountry_AsJOSN.includes(item)));
// console.log('OOoo', filterData.map(e => e.destinationCountry_AsJOSN), filterData.map(e => e.productType));
const CJCount = filterData.length; // filterData.reduce((r, c) => r + c.CJCount, 0);
const YJLY = filterData.reduce((r, c) => r + price_to_number(c.ML), 0);
const filterDataYear = yearData
.filter((ele) => ['泰国水灯节'].every((item) => ele.productType.toLocaleLowerCase().indexOf(item) === -1))
.filter((ele) => exceptContry.every((item) => !ele.destinationCountry_AsJOSN.includes(item)));
const rowYearData = { CJCount: filterDataYear.length, YJLY: filterDataYear.reduce((r, c) => r + price_to_number(c.ML), 0) };
// console.log('OOoo year', filterDataYear.map(e => e.destinationCountry_AsJOSN), filterDataYear.map(e => e.productType));
const filterDataYear2 = yearData2
.filter((ele) => ['泰国水灯节'].every((item) => ele.productType.toLocaleLowerCase().indexOf(item) === -1))
.filter((ele) => exceptContry.every((item) => !ele.destinationCountry_AsJOSN.includes(item)));
const rowYearData2 = { CJCount: filterDataYear2.length, YJLY: filterDataYear2.reduce((r, c) => r + price_to_number(c.ML), 0) };
// console.log('Oo', filterDataYear2.map(e => e.destinationCountry_AsJOSN), filterDataYear2);
// console.log('Oo row', rowYearData2);
const rowYear = {
YJLY: price_to_number(rowYearData.YJLY), CJCount: rowYearData.CJCount, GroupCount: rowYearData.CJCount,
YJLY2: price_to_number(rowYearData2.YJLY), CJCount2: rowYearData2.CJCount, GroupCount2: rowYearData2.CJCount,
};
return { GroupCount:CJCount, CJCount, YJLY, rowYear, rawData: filterData, rawYearData: filterDataYear, rawYearData2: filterDataYear2 };
};
class MeetingData {
constructor(rootStore) {
this.rootStore = rootStore;
makeAutoObservable(this);
}
searchValues = {
DateType: { key: 'applyDate', value: 'applyDate', label: '提交日期' },
};
setSearchValues(body) {
this.searchValues = body;
}
GHTableData = [];
GHTableLoading = false;
/**
* 获取市场订单数据 ---------------------------------------------------------------------------------------------------
*/
dataGHOrder = async (param) => {
// console.log('dataGH', param);
this.GHTableLoading = true;
const defaultParam = { DateType: 'applyDate' };
// 本周
const CHData = await getDetailData({ ...param, ...defaultParam, 'DepartmentList': '1', 'WebCode': 'All' });
const exceptCHData = await getDetailData({ ...param, ...defaultParam, 'DepartmentList': '28,33', 'WebCode': 'All' });
const yearStart = moment().startOf("year").format(DATE_FORMAT);
/** 截至今年 - 行 */
const [
{ ordercountTotal1: CHDataYear },
{ ordercount1: exceptCHDataYear },
] = await Promise.all([
getOrderCountByType({ ...param, ...defaultParam, Date1: yearStart, 'DepartmentList': '1', 'WebCode': 'All', OrderType: 'LineClass' }),
getOrderCountByType({ ...param, ...defaultParam, Date1: yearStart, 'DepartmentList': '28,33', 'WebCode': 'All', OrderType: 'Product' }),
]);
// const { ordercountTotal1: CHDataYear } = await getOrderCountByType({ ...param, ...defaultParam, Date1: yearStart, 'DepartmentList': '1', 'WebCode': 'All', OrderType: 'LineClass' });
// const { ordercount1: exceptCHDataYear } = await getOrderCountByType({ ...param, ...defaultParam, Date1: yearStart, 'DepartmentList': '28,33', 'WebCode': 'All', OrderType: 'Product' });
/** 截至今年 - 列 */
const [
{ ordercount1: ColLineClassDataYear },
{ ordercountTotal1: ColToBDataYear },
{ ordercountTotal1: ColExternalDataYear },
] = await Promise.all([
getOrderCountByType({ ...param, ...defaultParam, Date1: yearStart, 'DepartmentList': '1,2,28,7,33', 'WebCode': 'All', OrderType: 'LineClass' }),
getOrderCountByType({ ...param, ...defaultParam, Date1: yearStart, 'DepartmentList': '1,2,28,7,33', 'WebCode': 'GHTOBHW,GHTOBZG', OrderType: 'LineClass'}),
getOrderCountByType({ ...param, ...defaultParam, Date1: yearStart, 'DepartmentList': '1,2,28,7,33', 'WebCode': 'ZWQD', OrderType: 'LineClass'}),
]);
// const { ordercount1: ColLineClassDataYear } = await getOrderCountByType({ ...param, ...defaultParam, Date1: yearStart, 'DepartmentList': '1,2,28,7,33', 'WebCode': 'All', OrderType: 'LineClass' });
// const { ordercountTotal1: ColToBDataYear } = await getOrderCountByType({ ...param, ...defaultParam, Date1: yearStart, 'DepartmentList': '1,2,28,7,33', 'WebCode': 'GHTOBHW,GHTOBZG', OrderType: 'LineClass' });
// const { ordercountTotal1: ColExternalDataYear } = await getOrderCountByType({ ...param, ...defaultParam, Date1: yearStart, 'DepartmentList': '1,2,28,7,33', 'WebCode': 'ZWQD', OrderType: 'LineClass' });
// 老客户
const yearDetail = await getDetailData({ ...param, ...defaultParam, Date1: yearStart, '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,
external: ColExternalDataYear.OrderCount,
};
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', 'external', '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 });
runInAction(() => {
this.GHTableData = rows;
this.GHTableLoading = false;
});
};
GHSalesTableData = [];
GHSalesLoading = false;
/**
* 获取GH销售数据 ---------------------------------------------------------------------------------------------------
*/
dataGHSales = async (param) => {
this.GHSalesLoading = true;
const salesParam = { ...param, DateType: 'confirmDate', WebCode: 'CHT,AH,GH,GHKYZG,GHKYHW,ZWQD', OrderType:'ALL', }; // WebCode: 不含分销
const [
{ total1: CHSalesData }, // 不含分销
{ total1: AHSalesData }, // 不含分销
{ total1: GHSalesData }, // 不含分销
{ total1: partnerSalesData },
{ total1: totalSalesData },
] = await Promise.all([
getDepartmentOrderMLByType({...salesParam, DepartmentList: '1,2', }),
getDepartmentOrderMLByType({...salesParam, DepartmentList: '28', }),
getDepartmentOrderMLByType({...salesParam, DepartmentList: '33', }),
getDepartmentOrderMLByType({...salesParam, DepartmentList: '1,2,28,33',WebCode: 'GHTOBHW,GHTOBZG',}),
getDepartmentOrderMLByType({...salesParam, DepartmentList: '1,2,28,33',WebCode: 'ALL',})
]);
// const { total1: CHSalesDataTotal } = await getDepartmentOrderMLByType({...salesParam, DepartmentList: '1,2', WebCode: 'ALL',});
// const { total1: CHPartnerSalesData } = await getDepartmentOrderMLByType({...salesParam, DepartmentList: '1,2', WebCode: 'GHTOBHW,GHTOBZG', });
// const { total1: AHSalesDataTotal } = await getDepartmentOrderMLByType({...salesParam, DepartmentList: '28',WebCode: 'ALL',});
// const { total1: AHpartnerSalesData } = await getDepartmentOrderMLByType({...salesParam, DepartmentList: '28', WebCode: 'GHTOBHW,GHTOBZG', });
// const { total1: GHSalesDataTotal } = await getDepartmentOrderMLByType({...salesParam, DepartmentList: '33',WebCode: 'ALL',});
// const { total1: GHpartnerSalesData } = await getDepartmentOrderMLByType({...salesParam, DepartmentList: '33', WebCode: 'GHTOBHW,GHTOBZG', });
// 分销
// const CHSalesData0 = {'COLI_CJCount': CHSalesDataTotal.COLI_CJCount-CHPartnerSalesData.COLI_CJCount, 'COLI_ML2': CHSalesDataTotal.COLI_ML2-CHPartnerSalesData.COLI_ML2};
// const AHSalesData0 = {'COLI_CJCount': AHSalesDataTotal.COLI_CJCount-AHpartnerSalesData.COLI_CJCount, 'COLI_ML2': AHSalesDataTotal.COLI_ML2-AHpartnerSalesData.COLI_ML2};
// const GHSalesData0 = {'COLI_CJCount': GHSalesDataTotal.COLI_CJCount-GHpartnerSalesData.COLI_CJCount, 'COLI_ML2': GHSalesDataTotal.COLI_ML2-GHpartnerSalesData.COLI_ML2};
// const partnerSalesData0 = {'COLI_CJCount': CHPartnerSalesData.COLI_CJCount+AHpartnerSalesData.COLI_CJCount, 'COLI_ML2': CHPartnerSalesData.COLI_ML2+AHpartnerSalesData.COLI_ML2};
// const totalSalesData0 = {
// 'COLI_CJCount': CHSalesDataTotal.COLI_CJCount + AHSalesDataTotal.COLI_CJCount + GHSalesDataTotal.COLI_CJCount,
// 'COLI_ML2': CHSalesDataTotal.COLI_ML2 + AHSalesDataTotal.COLI_ML2 + GHSalesDataTotal.COLI_ML2,
// };
const yearStart = moment().startOf("year").format(DATE_FORMAT);
const yearEnd = moment().endOf("year").format(SMALL_DATETIME_FORMAT);
/** 截至今年 - 成交 */
const [
{ total1: CHDataYear },
{ total1: AHDataYear },
{ total1: GHDataYear },
{ total1: partnerDataYear },
{ total1: totalDataYear },
] = await Promise.all([
getDepartmentOrderMLByType({...salesParam, Date1: yearStart, DepartmentList: '1,2', }),
getDepartmentOrderMLByType({...salesParam, Date1: yearStart, DepartmentList: '28', }),
getDepartmentOrderMLByType({...salesParam, Date1: yearStart, DepartmentList: '33', }),
getDepartmentOrderMLByType({...salesParam, Date1: yearStart, DepartmentList: '1,2,28,7,33',WebCode: 'GHTOBHW,GHTOBZG',}),
getDepartmentOrderMLByType({...salesParam, Date1: yearStart, DepartmentList: '1,2,28,7,33',WebCode: 'ALL',})
]);
// const { total1: CHDataYear } = await getDepartmentOrderMLByType({...salesParam, Date1: yearStart, DepartmentList: '1,2', });
// const { total1: AHDataYear } = await getDepartmentOrderMLByType({...salesParam, Date1: yearStart, DepartmentList: '28', });
// const { total1: GHDataYear } = await getDepartmentOrderMLByType({...salesParam, Date1: yearStart, DepartmentList: '33', });
// const { total1: partnerDataYear } = await getDepartmentOrderMLByType({...salesParam, Date1: yearStart, DepartmentList: '1,2,28,7,33', WebCode: 'GHTOBHW,GHTOBZG', });
// const { total1: totalDataYear } = await getDepartmentOrderMLByType({...salesParam, Date1: yearStart, DepartmentList: '1,2,28,7,33', WebCode: 'ALL', });
/** 截至今年 - 走团 */
const [
{ total1: CHStartDataYear },
{ total1: AHStartDataYear },
{ total1: GHStartDataYear },
{ total1: partnerStartDataYear },
{ total1: totalStartDataYear },
] = await Promise.all([
getDepartmentOrderMLByType({...salesParam, Date1: yearStart, DepartmentList: '1,2', DateType: 'startDate' }),
getDepartmentOrderMLByType({...salesParam, Date1: yearStart, DepartmentList: '28', DateType: 'startDate' }),
getDepartmentOrderMLByType({...salesParam, Date1: yearStart,DepartmentList: '33', DateType: 'startDate' }),
/** 截至今年 - 走团 - 分销 */
getDepartmentOrderMLByType({...salesParam, Date1: yearStart, DepartmentList: '1,2,28,7,33',WebCode: 'GHTOBHW,GHTOBZG', DateType: 'startDate',}),
getDepartmentOrderMLByType({...salesParam, Date1: yearStart, DepartmentList: '1,2,28,7,33',WebCode: 'ALL', DateType: 'startDate',})
]);
// const { total1: CHStartDataYear } = await getDepartmentOrderMLByType({...salesParam, Date1: yearStart,DepartmentList: '1,2', DateType: 'startDate' });
// const { total1: AHStartDataYear } = await getDepartmentOrderMLByType({...salesParam, Date1: yearStart,DepartmentList: '28', DateType: 'startDate' });
// const { total1: GHStartDataYear } = await getDepartmentOrderMLByType({...salesParam, Date1: yearStart,DepartmentList: '33', DateType: 'startDate' });
/** 截至今年 - 走团 - 分销 */
// const { total1: partnerStartDataYear } = await getDepartmentOrderMLByType({...salesParam, Date1: yearStart,DepartmentList: '1,2,28,7,33', WebCode: 'GHTOBHW,GHTOBZG', DateType: 'startDate' });
// const { total1: totalStartDataYear } = await getDepartmentOrderMLByType({...salesParam, Date1: yearStart,DepartmentList: '1,2,28,7,33', WebCode: 'ALL', DateType: 'startDate' });
const rows = [
{
key: 'ch',
label: 'CH(不含分销)',
YJLY: price_to_number(CHSalesData.COLI_ML2),
CJCount: (CHSalesData.COLI_CJCount),
rowYear: { YJLY: price_to_number(CHDataYear.COLI_ML2), CJCount: CHDataYear.COLI_CJCount, YJLY2: price_to_number(CHStartDataYear.COLI_ML2) },
},
{
key: 'ah',
label: 'AH(不含分销)',
YJLY: price_to_number(AHSalesData.COLI_ML2),
CJCount: (AHSalesData.COLI_CJCount),
rowYear: { YJLY: price_to_number(AHDataYear.COLI_ML2), CJCount: AHDataYear.COLI_CJCount, YJLY2: price_to_number(AHStartDataYear.COLI_ML2) },
},
{
key: 'partner',
label: '分销',
YJLY: price_to_number(partnerSalesData.COLI_ML2),
CJCount: (partnerSalesData.COLI_CJCount),
rowYear: { YJLY: price_to_number(partnerDataYear.COLI_ML2), CJCount: partnerDataYear.COLI_CJCount, YJLY2: price_to_number(partnerStartDataYear.COLI_ML2) },
},
{
key: 'gh',
label: 'GH(不含分销)',
YJLY: price_to_number(GHSalesData.COLI_ML2),
CJCount: (GHSalesData.COLI_CJCount),
rowYear: { YJLY: price_to_number(GHDataYear.COLI_ML2), CJCount: GHDataYear.COLI_CJCount, YJLY2: price_to_number(GHStartDataYear.COLI_ML2) },
},
{
key: 'total',
label: '合计',
YJLY: price_to_number(totalSalesData.COLI_ML2),
CJCount: (totalSalesData.COLI_CJCount),
rowYear: { YJLY: price_to_number(totalDataYear.COLI_ML2), CJCount: totalDataYear.COLI_CJCount, YJLY2: price_to_number(totalStartDataYear.COLI_ML2) },
},
];
runInAction(() => {
this.GHSalesTableData = rows;
this.GHSalesLoading = false;
});
};
GHServiceTableData = [];
GHServiceLoading = false;
/**
* 获取GH服务数据 ---------------------------------------------------------------------------------------------------
*/
dataGHService = async (param) => {
this.GHServiceLoading = true;
const serviceParam = { ...param, DateType: 'startDate', 'WebCode': 'All' };
// 走团数
const [
{ ordercountTotal1: { OrderCount: CHGroupCount } },
{ ordercountTotal1: { OrderCount: AHGroupCount } },
{ ordercountTotal1: { OrderCount: GHGroupCount } },
] = await Promise.all([
getOrderCountByType({ ...serviceParam, 'DepartmentList': '1,2', OrderType: 'Form'}),
getOrderCountByType({ ...serviceParam, 'DepartmentList': '28', OrderType: 'Form'}),
getOrderCountByType({ ...serviceParam, 'DepartmentList': '33', OrderType: 'Form'}),
]);
// 走团数 - 年
// * 走团: 整团数, 而非各地接社/目的地的总和
const yearStart = moment().startOf("year").format(DATE_FORMAT);
const [
{ ordercountTotal1: { OrderCount: CHGroupCountYear } },
{ ordercountTotal1: { OrderCount: AHGroupCountYear } },
{ ordercountTotal1: { OrderCount: GHGroupCountYear } },
] = await Promise.all([
getOrderCountByType({ ...serviceParam, 'DepartmentList': '1,2', OrderType: 'Form', Date1: yearStart, }),
getOrderCountByType({ ...serviceParam, 'DepartmentList': '28', OrderType: 'Form', Date1: yearStart, }),
getOrderCountByType({ ...serviceParam, 'DepartmentList': '33', OrderType: 'Form', Date1: yearStart, }),
]);
// 好评数
const [
{ total1: { GoodCount: CHGoodCount } },
{ total1: { GoodCount: AHGoodCount } },
{ total1: { GoodCount: GHGoodCount } },
] = await Promise.all([
getAgentGroupInfoALL({ ...serviceParam, 'DepartmentList': '1,2', }),
getAgentGroupInfoALL({ ...serviceParam, 'DepartmentList': '28', }),
getAgentGroupInfoALL({ ...serviceParam, 'DepartmentList': '33', }),
]);
// 好评数 - 年
const [
{ total1: { GoodCount: CHGoodCountYear, } },
{ total1: { GoodCount: AHGoodCountYear, } },
{ total1: { GoodCount: GHGoodCountYear, } },
] = await Promise.all([
getAgentGroupInfoALL({ ...serviceParam, Date1: yearStart, 'DepartmentList': '1,2', }),
getAgentGroupInfoALL({ ...serviceParam, Date1: yearStart, 'DepartmentList': '28', }),
getAgentGroupInfoALL({ ...serviceParam, Date1: yearStart, 'DepartmentList': '33', }),
]);
const rows = [
{ key: 'ch', label: 'CH', GoodCount: CHGoodCount, GroupCount: CHGroupCount, rowYear: { GroupCount: CHGroupCountYear, GoodCount: CHGoodCountYear } },
{ key: 'ah', label: 'AH', GoodCount: AHGoodCount, GroupCount: AHGroupCount, rowYear: { GroupCount: AHGroupCountYear, GoodCount: AHGoodCountYear } },
{ key: 'Gh', label: 'GH', GoodCount: GHGoodCount, GroupCount: GHGroupCount, rowYear: { GroupCount: GHGroupCountYear, GoodCount: GHGoodCountYear } },
];
// const GHRowWeek = { GoodCount: GHGoodCountWeek, GroupCount: 0 };
// const columnsSum = ['GoodCount', 'GroupCount'].reduce((r, col) => ({ ...r, [col]: [...rows, GHRowWeek].reduce((rr, row) => rr + (row[col] || 0), 0) }), {});
// const allYearData = rows.map((row) => row.rowYear).concat([{ GoodCount: GHGoodCountYear, GroupCount: 0 }]);
// // console.log(allYearData);
// const rowYear = ['GoodCount', 'GroupCount', ].reduce((r, col) => ({ ...r, [col]: allYearData.reduce((rr, row) => rr + (row[col] || 0), 0) }), {});
// rows.push({ key: 'columnSum', label: '合计', ...columnsSum, rowYear });
// console.log(rows);
runInAction(() => {
this.GHServiceTableData = rows;
this.GHServiceLoading = false;
});
};
}
export default MeetingData;

@ -0,0 +1,134 @@
import { useContext } from 'react';
import { observer } from 'mobx-react';
import { stores_Context } from '../config';
import { Table, Row, Col, Divider, Tooltip } from 'antd';
import { InfoCircleOutlined } from '@ant-design/icons';
import SearchForm from '../components/search/SearchForm';
import { TableExportBtn } from './../components/Data';
import { fixTo2Decimals } from './../utils/commons';
const numberConvert10K = (number, scale = 10) => {
return fixTo2Decimals(number / (1000 * scale)) + '';
};
// TdCellDataTable
const TdCell = (tdprops) => {
// onMouseEnter, onMouseLeave
const { onMouseEnter, onMouseLeave, ...restProps } = tdprops;
return <td {...restProps} />;
};
export default observer((props) => {
const { date_picker_store: searchFormStore, MeetingData2025Store: MeetingDataStore } = useContext(stores_Context);
const { formValues, formValuesToSub, siderBroken } = searchFormStore;
const dataRefresh = async (obj) => {
MeetingDataStore.dataGHOrder({ ...(obj || formValuesToSub) });
MeetingDataStore.dataGHSales({ ...(obj || formValuesToSub) });
MeetingDataStore.dataGHService({ ...(obj || formValuesToSub) });
};
const targetTableProps = {
loading: MeetingDataStore.GHLoading,
// sticky: true,
scroll: { x: 1000, y: 400 },
pagination: false,
components: { body: { cell: TdCell } },
orderColumns: [
{ key: 'label', title: '市场:', dataIndex: 'label', width: 150 },
{
key: 'LineClass_Origin',
titleX: '网站',
title: () => (
<>
网站{' '}
<Tooltip title="网前自然订单">
<InfoCircleOutlined />
</Tooltip>
</>
),
dataIndex: 'LineClass_Origin',
},
{
key: 'external',
titleX: '站外渠道',
title: () => (
<>
站外渠道{' '}
<Tooltip title="Facebook, Pinterest, Youtube, Instagram">
<InfoCircleOutlined />
</Tooltip>
</>
),
dataIndex: 'external',
},
{ key: 'LineClass_PPC', title: 'PPC', dataIndex: 'LineClass_PPC' },
{ key: 'toB', title: 'To B', dataIndex: 'toB' },
{ key: 'isOld1', title: 'C老客户', dataIndex: 'isOld1' },
{ key: 'total', title: '合计', dataIndex: 'total' },
{ key: 'rowYear', title: '截至年订单数', dataIndex: 'rowYear' },
// { key: 'groupsLabel2', title: '', dataIndex: 'groupsLabel2' },
// { key: 'groupsLabel2', title: '', dataIndex: 'groupsLabel2' },
],
salesColumns: [
{ key: 'label', title: '顾问:', dataIndex: 'label', width: 150 },
{ key: 'CJCount', title: '成交个数', dataIndex: 'CJCount' },
{ key: 'YJLY', title: '成交毛利(万)', dataIndex: 'YJLY', render: (text) => numberConvert10K(text) },
{ key: 'CJCount1', title: '年成交个数', dataIndex: ['rowYear', 'CJCount'] },
{ key: 'YJLY1', title: '年成交毛利(万)', dataIndex: ['rowYear', 'YJLY'], render: (text) => numberConvert10K(text) },
{ key: 'YJLY2', title: '年走团毛利(万)', dataIndex: ['rowYear', 'YJLY2'], render: (text) => numberConvert10K(text) },
],
serviceColumns: [
{ key: 'label', title: '客服:', dataIndex: 'label', width: 150 },
{ key: 'GroupCount', title: '走团个数', dataIndex: 'GroupCount' },
{ key: 'GoodCount', title: '好评个数', dataIndex: 'GoodCount' },
{ key: 'GroupCount1', title: '年走团个数', dataIndex: ['rowYear', 'GroupCount'] },
{ key: 'GoodCount2', title: '年好评个数', dataIndex: ['rowYear', 'GoodCount'] },
],
};
return (
<>
<Row gutter={16} className={siderBroken ? '' : 'sticky-top'}>
<Col className="gutter-row" span={24}>
<SearchForm
defaultValue={{
initialValue: {
...formValues,
...MeetingDataStore.searchValues,
// ...searchInitial,
},
shows: ['IncludeTickets', 'dates'], // 'country'
fieldProps: {
dates: { hide_vs: true },
},
}}
onSubmit={(_err, obj, form, str) => {
MeetingDataStore.setSearchValues(form);
dataRefresh(obj);
}}
/>
</Col>
</Row>
<h2>GH例会数据 2025</h2>
<Divider orientation="left" plain>
<span>GH: 市场</span>
<TableExportBtn label={`${formValuesToSub.Date1}-GH: 市场`} {...{ columns: targetTableProps.orderColumns, dataSource: MeetingDataStore.GHTableData }} style={{ marginLeft: 'auto' }} />
</Divider>
<Table {...targetTableProps} key={'GHTable'} dataSource={MeetingDataStore.GHTableData} columns={targetTableProps.orderColumns} loading={MeetingDataStore.GHTableLoading} />
<Divider orientation="left" plain>
<span>GH: 顾问成交</span>
<TableExportBtn label={`${formValuesToSub.Date1}-GH: 顾问成交`} {...{ columns: targetTableProps.salesColumns, dataSource: MeetingDataStore.GHSalesTableData }} />
</Divider>
<Table {...targetTableProps} key={'GHSales'} dataSource={MeetingDataStore.GHSalesTableData} columns={targetTableProps.salesColumns} loading={MeetingDataStore.GHSalesLoading} />
<Divider orientation="left" plain>
<span>GH: 客服</span>
<TableExportBtn label={`${formValuesToSub.Date1}-GH: 客服`} {...{ columns: targetTableProps.serviceColumns, dataSource: MeetingDataStore.GHServiceTableData }} />
</Divider>
<Table {...targetTableProps} key={'GHService'} dataSource={MeetingDataStore.GHServiceTableData} columns={targetTableProps.serviceColumns} loading={MeetingDataStore.GHServiceLoading} />
</>
);
});

@ -48,6 +48,10 @@ const Sale = () => {
...config_data, ...config_data,
...{ ...{
//seriesField: "OPI_Name",// //seriesField: "OPI_Name",//
columnWidthRatio: 0.28,
// dodgePadding: 1,
// minColumnWidth: 5,
// maxColumnWidth: 15,
label: { label: {
position: 'top', position: 'top',
}, },

Loading…
Cancel
Save