Merge branch 'main' into feature/hotel-cruise

# Conflicts:
#	src/stores/CustomerServices.js
main
Lei OT 3 months ago
commit a32943fffb

4
package-lock.json generated

@ -1,12 +1,12 @@
{
"name": "haina-dashboard",
"version": "2.10.0",
"version": "2.10.7",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "haina-dashboard",
"version": "2.10.0",
"version": "2.10.7",
"dependencies": {
"@ant-design/charts": "^1.4.2",
"@ant-design/pro-components": "^2.6.16",

@ -1,6 +1,6 @@
{
"name": "haina-dashboard",
"version": "2.10.0",
"version": "2.10.7",
"private": true,
"dependencies": {
"@ant-design/charts": "^1.4.2",

@ -53,7 +53,7 @@ import { stores_Context, APP_VERSION } from './config';
import { WaterMark } from '@ant-design/pro-components';
import CooperationIcon from './components/icons/CooperationIcon';
import OPDashboard from './views/OPDashboard';
import OPActivity from './views/OPActivity';
import OPProcess from './views/OPProcess';
import OPRisk from './views/OPRisk';
import Cruise from './views/Cruise';
import Hotel from './views/Hotel';
@ -171,7 +171,7 @@ const App = () => {
children: [
// { key: 'xx', type: 'divider' },
{ key: 'op_dashboard', label: <NavLink to="/op_dashboard">结果</NavLink> },
// { key: 'op_activity', label: <NavLink to="/op_activity"></NavLink> },
{ key: 'op_process', label: <NavLink to="/op_process">过程</NavLink> },
// { key: 'op_risk', label: <NavLink to="/op_risk"></NavLink> },
],
},
@ -278,7 +278,7 @@ const App = () => {
<Route path="/distribution" element={<Distribution />} />
<Route path="/:page/pivot" element={<DataPivot />} />
<Route path="/op_dashboard" element={<OPDashboard />} />
<Route path="/op_activity" element={<OPActivity />} />
<Route path="/op_process" element={<OPProcess />} />
<Route path="/op_risk" element={<OPRisk />} />
</Route>
</Routes>

@ -1,16 +1,17 @@
import React, { useContext, useEffect } from 'react';
import React, { useContext } from 'react';
import { Row, Col, Divider, Table, Tooltip } from 'antd';
import { InfoCircleOutlined } from '@ant-design/icons';
import { utils, writeFileXLSX } from 'xlsx';
import { stores_Context } from '../config';
import { observer } from 'mobx-react';
import SearchForm from './../components/search/SearchForm';
import LineWithAvg from '../components/LineWithAvg';
const Customer_care_regular = () => {
const { orders_store, date_picker_store, customer_store } = useContext(stores_Context);
const regular_data = customer_store.regular_data;
useEffect(() => {}, []);
// useEffect(() => {}, []);
return (
<div>
@ -66,7 +67,7 @@ const Customer_care_regular = () => {
<>
<span>{text}</span>&nbsp;&nbsp;
{<Tooltip key='total_data_tips' title={regular_data.total_data_tips}>
{index === 0 && regular_data.total_data_tips!=='' && <InfoCircleOutlined />}
{index === 0 && regular_data.total_data_tips!=='' && <InfoCircleOutlined className='ant-tag-gold' />}
</Tooltip>}
</>
),
@ -98,6 +99,11 @@ const Customer_care_regular = () => {
rowKey={(record) => record.ItemName}
/>
</Col>
<Col span={24}>
<LineWithAvg dataSource={regular_data.pivotData} loading={regular_data.detail_loading} xField={regular_data.pivotX} yField={regular_data.pivotY} seriesField='_ylabel' showSUM={true} />
</Col>
<Col span={24}>
<Divider orientation="right" plain>
<a
@ -112,7 +118,7 @@ const Customer_care_regular = () => {
<Table
id="table_to_xlsx"
pagination={false}
loading={regular_data.loading}
loading={regular_data.detail_loading}
dataSource={regular_data.data_detail}
scroll={{ x: 1200 }}
columns={[
@ -127,7 +133,7 @@ const Customer_care_regular = () => {
key: 'COLI_ApplyDate',
},
{
title: '订单状态',
title: '订单状态',width: '4rem',
dataIndex: 'OrderState',
key: 'OrderState',
render: (text, record) => <span>{text == 1 ? '成行' : '未成行'}</span>,
@ -188,6 +194,21 @@ const Customer_care_regular = () => {
dataIndex: 'COLI_LineClass',
key: 'COLI_LineClass',
},
{ title: '上次 订单号', dataIndex: 'coli_id_Last', key: 'coli_id_Last', width: '4em',
render: (_, r) => ({
props: { style: { backgroundColor: '#5B8FF9'+'1A' } },
children: _,
}), },
{ title: '上次 走团日期', dataIndex: 'COLI_OrderStartDate_Last', key: 'COLI_OrderStartDate_Last',width: '4em',
render: (_, r) => ({
props: { style: { backgroundColor: '#5B8FF9'+'1A' } },
children: _,
}), },
{ title: '上次 小组', dataIndex: 'Department_Last', key: 'Department_Last',width: '4em',
render: (_, r) => ({
props: { style: { backgroundColor: '#5B8FF9'+'1A' } },
children: _,
}), },
]}
size="small"
rowKey={(record) => record.COLI_ID}

@ -0,0 +1,168 @@
import React, { useEffect, useState } from 'react';
import { Row, Col, Spin } from 'antd';
import { Line } from '@ant-design/plots';
import { observer } from 'mobx-react';
import { dataFieldAlias } from '../libs/ht';
import DateGroupRadio from '../components/DateGroupRadio';
import { cloneDeep, groupBy, sortBy } from '../utils/commons';
export default observer((props) => {
const { dataSource: rawData, showAVG, showSUM, loading, ...config } = props;
const { xField, yField, yFieldAlias, seriesField } = config;
const [dataBeforeXChange, setDataBeforeXChange] = useState([]);
const [dataSource, setDataSource] = useState([]);
const [sumSeries, setSumSeries] = useState([]);
const line_config = {
// data: dataSource,
padding: 'auto',
xField,
yField,
seriesField,
// seriesField: 'rowLabel',
// xAxis: {
// type: 'timeCat',
// },
yAxis: {
min: 0,
maxTickInterval: 5,
},
meta: {
...cloneDeep(dataFieldAlias),
},
// smooth: true,
label: {}, //
legend: {
position: 'right-top',
// title: {
// text: ' ' + dataSource.reduce((a, b) => a + b.SumOrder, 0),
// },
itemMarginBottom: 12, //
},
tooltip: {
customItems: (originalItems) => {
return originalItems
.map((ele) => ({ ...ele, valueR: ele.data[yField] }))
.sort(sortBy('valueR'))
.reverse();
},
},
};
const [lineConfig, setLineConfig] = useState(cloneDeep(line_config));
useEffect(() => {
resetX();
return () => {};
}, [rawData]);
useEffect(() => {
if (lineChartX === 'day') {
setDataBeforeXChange(dataSource);
}
return () => {};
}, [dataSource]);
//
const [lineChartX, setLineChartX] = useState('day');
const orderCountDataMapper = { data1: 'data1', data2: undefined };
const orderCountDataFieldMapper = { 'dateKey': xField, 'valueKey': yField, 'seriesKey': seriesField, _f: 'sum' };
const resetX = () => {
setLineChartX('day');
setDataSource(rawData);
setDataBeforeXChange(rawData);
// ``线, ``线
const byDays = groupBy(rawData, xField);
const sumY = rawData.reduce((a, b) => a + b[yField], 0);
const avgVal = Math.round(sumY / (Object.keys(byDays).length));
const avgLine = [
{ type: 'text', position: ['start', avgVal], content: avgVal, offsetX: -15, style: { fill: '#F4664A', textBaseline: 'bottom' } },
{ type: 'line', start: [-10, avgVal], end: ['max', avgVal], style: { stroke: '#F4664A', lineDash: [2, 2] } },
];
setLineConfig({ ...lineConfig, yField, xField, annotations: avgLine });
if (showSUM) {
const _sumLine = Object.keys(byDays).reduce((r, _d) => {
const summaryVal = byDays[_d].reduce((rows, row) => rows + row[yField], 0);
r.push({ ...byDays[_d][0], [yField]: summaryVal, [seriesField]: '总计' });
return r;
}, []);
// console.log(_sumLine.map((ele) => ele[yField]));
setSumSeries(_sumLine);
}
};
const onChangeXDateFieldGroup = (value, data, avg1) => {
// console.log(value, data, avg1);
const _sumLine = [];
const { xField, yField, seriesField } = lineConfig;
const groupByDate = data.reduce((r, v) => {
(r[v[xField]] || (r[v[xField]] = [])).push(v);
return r;
}, {});
// console.log(groupByDate);
const _data = Object.keys(groupByDate).reduce((r, _d) => {
const summaryVal = groupByDate[_d].reduce((rows, row) => rows + row[yField], 0);
_sumLine.push({ ...groupByDate[_d][0], [yField]: summaryVal, [seriesField]: '总计' });
const xAxisGroup = groupByDate[_d].reduce((a, v) => {
(a[v[seriesField]] || (a[v[seriesField]] = [])).push(v);
return a;
}, {});
// console.log(xAxisGroup);
Object.keys(xAxisGroup).map((_group) => {
const summaryVal = xAxisGroup[_group].reduce((rows, row) => rows + row[yField], 0);
r.push({ ...xAxisGroup[_group][0], [yField]: summaryVal, });
return _group;
});
return r;
}, []);
// const _sum = Object.values(groupBy(_data, 'dateGroup')).reduce((ac, b) => ({...b, [yField]: 0}), {});
// console.log(xField, avg1);
// console.log('date source=====', _data);
setLineChartX(value);
setDataSource(_data);
if (showSUM) {
setSumSeries(_sumLine);
}
// setAvgLine1(avg1);
const avg1Int = Math.round(avg1);
const mergedConfig = { ...lineConfig,
annotations: [
{ type: 'text', position: ['start', avg1Int], content: avg1Int, offsetX: -15, style: { fill: '#F4664A', textBaseline: 'bottom' } },
{ type: 'line', start: [-10, avg1Int], end: ['max', avg1Int], style: { stroke: '#F4664A', lineDash: [2, 2] } },
],
};
// console.log(mergedConfig);
setLineConfig(mergedConfig);
};
return (
<section>
<Row gutter={16} justify={'space-between'} className="mb-1">
<Col flex={'auto'}>
<h3>
走势: <span style={{ fontSize: 'smaller' }}>{dataFieldAlias[lineConfig.yField].label}</span>
</h3>
</Col>
<Col style={{ textAlign: 'right' }} align={'end'}>
<DateGroupRadio
visible={true}
dataRaw={{ data1: dataBeforeXChange }}
onChange={onChangeXDateFieldGroup}
value={lineChartX}
dataMapper={orderCountDataMapper}
fieldMapper={orderCountDataFieldMapper}
/>
</Col>
</Row>
<Spin spinning={loading}>
<Line {...lineConfig} data={[].concat(dataSource, sumSeries)} />
</Spin>
</section>
);
});

@ -15,6 +15,7 @@ import DatePickerCharts from './DatePickerCharts';
import YearPickerCharts from './YearPickerCharts';
import SearchInput from './Input';
import { objectMapper, at, empty, isEmpty } from './../../utils/commons';
import { departureDateTypes } from './../../libs/ht';
import './search.css';
import HotelStarSelect from './HotelStarSelect';
@ -53,6 +54,11 @@ export default observer((props) => {
transform: (value) => value?.key || '',
default: '',
},
'departureDateType': {
key: 'DateType',
transform: (value) => value?.key || '',
default: '',
},
'HTBusinessUnits': {
key: 'HTBusinessUnits',
transform: (value) => {
@ -92,6 +98,11 @@ export default observer((props) => {
transform: (value) => Array.isArray(value) ? value.map((ele) => ele.key).join(',') : value ? (!isNaN(parseInt(value.key), 10) ? value.key : '') : '',
default: '',
},
'date': {
key: 'date',
transform: (value) => (value ? moment(value).format(SMALL_DATETIME_FORMAT) : undefined),
default: '',
},
'applyDate': [
{
key: 'Date1',
@ -172,7 +183,7 @@ export default observer((props) => {
},
};
let dest = {};
const { applyDate, applyDate2, year, yearDiff, dates, months, ...omittedValue } = values;
const { departureDateType, applyDate, applyDate2, year, yearDiff, dates, months, date, ...omittedValue } = values;
dest = { ...omittedValue, ...objectMapper(values, destinationObject) };
for (const key in dest) {
if (Object.prototype.hasOwnProperty.call(dest, key)) {
@ -392,6 +403,23 @@ function getFields(props) {
</Form.Item>,
fieldProps?.DateType?.col || 3
),
item(
'departureDateType',
99,
<Form.Item name={`departureDateType`} initialValue={at(props, 'initialValue.departureDateType')[0] || { key: 'departureDate', label: '抵达日期' }}>
<Select labelInValue={true}
style={{ width: '100%' }}
placeholder="选择日期类型"
>
{departureDateTypes.map((ele) => (
<Select.Option key={ele.key} value={ele.key} disabled={fieldProps?.departureDateType?.disabledKeys.includes(ele.key)}>
{ele.label}
</Select.Option>
))}
</Select>
</Form.Item>,
fieldProps?.departureDateType?.col || 3
),
item(
'years',
99,
@ -417,6 +445,14 @@ function getFields(props) {
</Form.Item>,
fieldProps?.dates?.col || midCol
),
item(
'date',
99,
<Form.Item name={`date`} initialValue={at(props, 'initialValue.date')[0]}>
<DatePicker picker="date" placeholder="日期" />
</Form.Item>,
fieldProps?.date?.col || midCol
),
item(
'operator',
99,

@ -66,8 +66,10 @@ export const overviewGroup = groups.slice(0, 3); // todo: 花梨鹰 APP Trippest
export const sites = [
{ value: '2', key: '2', label: 'CHT', code: 'CHT' },
{ value: '8', key: '8', label: 'AH', code: 'AH' },
{ value: '186', key: '186', label: 'JH', code: 'JH' },
{ value: '163', key: '163', label: 'GH', code: 'GH' },
{ value: '184', key: '184', label: '站外渠道', code: 'ZWQD' },
{ value: '184', key: '184', label: 'GH站外渠道 (中国)', code: 'ZWQD' },
{ value: '185', key: '185', label: 'GH站外渠道 (海外)', code: 'GH_ZWQD_HW' },
{ value: '28', key: '28', label: '客运中国', code: 'GHKYZG' },
{ value: '7', key: '7', label: '客运海外', code: 'GHKYHW' },
{ value: '172', key: '172', label: 'GHToB 海外', code: 'GHTOBHW' },
@ -102,6 +104,10 @@ export const dateTypes = [
{ key: 'confirmDate', value: 'confirmDate', label: '确认日期' },
{ key: 'startDate', value: 'startDate', label: '走团日期' },
];
export const departureDateTypes = [
...dateTypes,
{ key: 'departureDate', value: 'departureDate', label: '抵达日期' },
];
/**
* 结果字段
@ -203,17 +209,70 @@ const calcPPPriceRange = (value) => {
if (value < 0) {
return '--';
}
const step = 30; // step = 30 USD
const start = Math.floor(value / step) * step;
const end = start + step;
if (value >= 301) {
return `301-Infinity`;
return `301`;
}
return `${start === 0 ? start : (start+1)}-${end}`;
};
function calculateRangeScale(data, numScales = 36) {
if (!data || data.length === 0 || numScales <= 0) {
return [];
}
const sortedData = [...data].sort((a, b) => a - b);
const min = sortedData[0];
const max = sortedData[sortedData.length - 1];
if (min === max) {
return [roundToNice(min), roundToNice(min)];
}
const scales = [roundToNice(min)];
const scaleSize = sortedData.length / numScales;
for (let i = 1; i < numScales; i++) {
const index = Math.floor(i * scaleSize);
scales.push(roundToNice(sortedData[Math.min(index, sortedData.length - 1)]));
}
scales.push(roundToNice(max));
return [...new Set(scales)];
}
function roundToNice(value) {
if (value === 0) {
return 0;
}
const magnitude = Math.pow(10, Math.floor(Math.log10(Math.abs(value))));
const normalized = value / magnitude;
let rounded;
if (normalized < 1.5) {
rounded = Math.floor(normalized);
} else if (normalized < 3) {
rounded = Math.floor(normalized * 2) / 2; // round to 0.5
} else if (normalized < 5) {
rounded = Math.floor(normalized/2) * 2; // round to 2
} else if (normalized < 7.5) {
rounded = Math.floor(normalized / 5) * 5;
} else {
// rounded = Math.floor(normalized / 5) * 5;
rounded = Math.floor(normalized / 10) * 10;
}
return rounded * magnitude;
};
const findRange = (value, scale) => {
if (value < scale[0]) {
return `0-${scale[0]}`; // `Value ${value} is below the scale range.`;
}
for (let i = 1; i < scale.length; i++) {
if (value >= scale[i - 1] && value < scale[i]) {
return `${scale[i - 1]}-${scale[i]}`; // `Value ${value} is in the range [${scale[i - 1]}, ${scale[i]})`;
}
}
if (value >= scale[scale.length - 1]) {
return `${scale[scale.length - 1]}`; // `Value ${value} is in the range [${scale[scale.length - 1]}, Infinity)`;
}
};
const SumML_range = [1, 1.5, 2, 3, 4].map(v => v * 10000);
/**
* 数据透视计算
* @param {object[]} data
@ -227,19 +286,24 @@ export const pivotBy = (_data, [rows, columns, date]) => {
// if (groupbyKeys.includes('PPPriceRange')) {
// }
// 补充计算的字段
const RTXF_WB_values = cloneDeep(_data).map(ele => ele.RTXF_WB);
// const max_RTXF_WB = Math.max(...RTXF_WB_values);
const RTXF_WB_range = calculateRangeScale(RTXF_WB_values);
let data = cloneDeep(_data).map(ele => {
ele.PPPrice = (Number(ele.orderState) === 1 && ele.tourdays && ele.personNum) ? fixToInt(ele.quotePrice / ele.tourdays / ele.personNum) : -1;
ele.PPPrice = (Number(ele.orderState) === 1 && ele.tourdays && ele.personNum) ? fixToInt(ele.quotePrice / ele.tourdays / ele.personNum) : -1; // 报价: 人均天
ele.PPPriceRange = calcPPPriceRange(ele.PPPrice);
ele.RTXF_WB_range = findRange(ele.RTXF_WB, RTXF_WB_range);
ele.IsOld_txt = ele.IsOld === '1' ? '老客户' : '否';
ele.isCusCommend_txt = ele.isCusCommend === '1' ? '老客户推荐' : '否';
const hasOld = (ele.IsOld === '1' || ele.isCusCommend === '1') ? 1 : 0;
ele.hasOld = hasOld;
ele.hasOld_txt = hasOld === 1 ? '老客户(推荐)' : '';
ele.SumML_ctxt1 = ele.ML > 10000 ? '1W+' : '1W-';
ele.SumML_ctxt1_5 = ele.ML > 15000 ? '1.5W+' : '1.5W-';
ele.SumML_ctxt2 = ele.ML > 20000 ? '2W+' : '2W-';
ele.SumML_ctxt3 = ele.ML > 30000 ? '3W+' : '3W-';
ele.SumML_ctxt4 = ele.ML > 40000 ? '4W+' : '4W-';
// ele.SumML_ctxt1 = ele.ML > 10000 ? '1W+' : '1W-';
// ele.SumML_ctxt1_5 = ele.ML > 15000 ? '1.5W+' : '1.5W-';
// ele.SumML_ctxt2 = ele.ML > 20000 ? '2W+' : '2W-';
// ele.SumML_ctxt3 = ele.ML > 30000 ? '3W+' : '3W-';
// ele.SumML_ctxt4 = ele.ML > 40000 ? '4W+' : '4W-';
ele.SumML_ctxt = findRange(ele.ML, SumML_range);
return ele;
});
// 数组的字段值, 拆分处理
@ -255,6 +319,18 @@ export const pivotBy = (_data, [rows, columns, date]) => {
return r;
}, []);
}
if (groupbyKeys.includes('destinations_AsJOSN')) {
data = _data.reduce((r, v, i) => {
const vjson = isEmpty(v.destinations_AsJOSN) ? [] : v.destinations_AsJOSN;
const xv = (vjson).reduce((rv, cv, vi) => {
rv.push({...v, destinations_AsJOSN: cv, key: vi === 0 ? v.key : `${v.key}@${cv}`});
return rv;
}, []);
r = r.concat(xv);
return r;
}, []);
}
const getKeys = (keys) => keys.map((keyField) => [...new Set(data.map((f) => f[keyField]))]);
const [rowsKeys, columnsKeys, dateKeys] = [getKeys(rows), getKeys(columns), [getKeys([date])[0].filter(s => s)]];

@ -3,7 +3,7 @@ import moment from "moment";
import { NavLink } from "react-router-dom";
import * as config from "../config";
import * as req from '../utils/request';
import { prepareUrl } from '../utils/commons';
import { groupBy, prepareUrl } from '../utils/commons';
class CustomerServices {
@ -13,7 +13,7 @@ class CustomerServices {
this.endDate = moment().endOf('week').subtract(7, 'days');
this.startDateString = this.startDate.format(config.DATE_FORMAT);
this.endDateString = this.endDate.format(config.DATE_FORMAT) + '%2023:59';
this.dateType = 'startDate';
this.dateType = 'departureDate';
this.inProgress = false;
this.selectedAgent = '';
this.selectedTeam = '';
@ -43,8 +43,8 @@ class CustomerServices {
.append('DateType', this.dateType)
.append('Date1', this.startDateString)
.append('Date2', this.endDateString)
.append('OldDate1', this.startDateString)
.append('OldDate2', this.endDateString)
.append('OldDate1', this.startDateDiffString)
.append('OldDate2', this.endDateDiffString)
.append('VEI_SN', this.selectedAgent)
.append('DepList', this.selectedTeam)
.append('Country', this.selectedCountry)
@ -53,8 +53,9 @@ class CustomerServices {
.then(json => {
if (json.errcode === 0) {
runInAction(() => {
this.agentGroupList = json.result1;
const total1 = json.total1;
const splitTotalList = groupBy(json.result1, row => row.EOI_ObjSN === -1 ? '0' : '1');
this.agentGroupList = splitTotalList['1'];
const total1 = splitTotalList['0']?.[0] || {}; // json.total1;
this.agentGroupListColumns = [
{
title: '地接社名称',
@ -293,8 +294,10 @@ class CustomerServices {
.then(json => {
if (json.errcode === 0) {
runInAction(() => {
this.destinationGroupCount = json.result1;
const total1 = json.total1;
const splitTotalList = groupBy(json.result1, row => row.COLD_ServiceCity === -1 ? '0' : '1');
this.agentGroupList = splitTotalList['1'];
const total1 = splitTotalList['0']?.[0] || {}; // json.total1;
this.destinationGroupCount = splitTotalList['1'];
this.destinationGroupCountColumns = [
{
title: '城市',
@ -342,7 +345,7 @@ class CustomerServices {
dataIndex: 'TotalCost',
sorter: (a, b) => a.TotalCost - b.TotalCost,
children: [{
title: total1.totalcost,
title: total1.TotalCost,
dataIndex: 'TotalCost'
}
]
@ -352,7 +355,7 @@ class CustomerServices {
dataIndex: 'TotalPrice',
sorter: (a, b) => a.TotalPrice - b.TotalPrice,
children: [{
title: total1.totalprice,
title: total1.TotalPrice,
dataIndex: 'TotalPrice'
}
]
@ -458,8 +461,8 @@ class CustomerServices {
}
searchValues = {
DateType: { key: 'startDate', label: '走团日期'},
countryArea: { key: 'china', label: '国内' },
DateType: { key: 'departureDate', label: '抵达日期'},
// departureDateType: { key: 'departureDate', label: '抵达日期'},
};
setSearchValues(obj, values) {
@ -467,6 +470,8 @@ class CustomerServices {
this.selectedAgent = obj.agency;
this.startDateString = obj.Date1;
this.endDateString = obj.Date2;
this.startDateDiffString = obj.DateDiff1;
this.endDateDiffString = obj.DateDiff2;
this.selectedCountry = obj.countryArea;
this.selectedTeam = obj.DepartmentList.replace('ALL', '');
this.selectedOrderStatus = obj.orderStatus;

@ -2,6 +2,8 @@ import {makeAutoObservable, runInAction} from "mobx";
import { fetchJSON } from '../utils/request';
import * as config from "../config";
import { groupsMappedByKey, sitesMappedByCode, pivotBy } from './../libs/ht';
import { sortBy } from "../utils/commons";
import moment from 'moment';
/**
* 用于透视的数据
@ -100,7 +102,10 @@ class CustomerStore {
// 老客户 beign
regular_customer_order(get_detail = false) {
let pivotByOrder = 'SumOrder';
let pivotByDate = 'applyDate';
this.regular_data.loading = true;
this.regular_data.detail_loading = get_detail;
const date_picker_store = this.rootStore.date_picker_store;
let url = '/service-tourdesign/RegularCusOrder';
url += '?Website=' + this.regular_data.webcode.toString() + '&DEI_SNList=' + this.regular_data.groups.toString();
@ -108,8 +113,12 @@ class CustomerStore {
url += '&ApplydateCheck=1&EntrancedateCheck=0&ConfirmDateCheck=0';
} else if(String(this.regular_data.date_type).toLowerCase() === 'confirmdate'){
url += '&ApplydateCheck=0&EntrancedateCheck=0&ConfirmDateCheck=1';
pivotByOrder = 'ConfirmOrder';
pivotByDate = 'confirmDate';
}else {
url += '&ApplydateCheck=0&EntrancedateCheck=1&ConfirmDateCheck=0';
pivotByOrder = 'ConfirmOrder';
pivotByDate = 'startDate';
}
url += '&ApplydateStart=' + date_picker_store.start_date.format(config.DATE_FORMAT) + '&ApplydateEnd=' + date_picker_store.end_date.format(config.SMALL_DATETIME_FORMAT);
url += '&EntrancedateStart=' + date_picker_store.start_date.format(config.DATE_FORMAT) + '&EntrancedateEnd=' + date_picker_store.end_date.format(config.SMALL_DATETIME_FORMAT);
@ -126,9 +135,30 @@ class CustomerStore {
.then((json) => {
runInAction(() => {
if (get_detail) {
this.regular_data.detail_loading = false;
this.regular_data.data_detail = json;
const dump_l = (json || []).filter(ele => ele.COLI_IsOld !== '' && ele.COLI_IsCusCommend !== '').length;
this.regular_data.total_data_tips = dump_l > 0 ? `包含 ${dump_l} 条同时勾选的数据` : '';
/** 使用明细数据画图 */
const data_detail = (json || []).map((ele) => ({
...ele,
key: ele.COLI_ID,
orderState: ele.OrderState,
applyDate: moment(ele.COLI_ApplyDate).format('YYYY-MM-DD'),
startDate: ele.COLI_OrderStartDate,
confirmDate: moment(ele.COLI_ConfirmDate).format('YYYY-MM-DD'),
}));
const { data: IsOldData, } = pivotBy(data_detail.filter(ele => ele.COLI_IsOld === '是'), [['COLI_IsOld', ], [], pivotByDate]);
const { data: isCusCommendData, } = pivotBy(data_detail.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));
// console.log('seriesData====', seriesData);
this.regular_data.pivotData = seriesData; // { IsOldData, isCusCommendData, };
this.regular_data.pivotY = pivotByOrder;
this.regular_data.pivotX = pivotByDate;
} else {
this.regular_data.data = json;
}
@ -159,6 +189,7 @@ class CustomerStore {
regular_data = {
loading: false,
detail_loading: false,
data: [],
data_detail: [],
total_data_tips: '',
@ -179,6 +210,10 @@ class CustomerStore {
WebCode: undefined, // ['ALL'].map(kk => sitesMappedByCode[kk]),
DateType: { key: 'applyDate', label: '提交日期'},
},
pivotData: [],
pivotY: 'SumOrder',
pivotX: 'applyDate',
};
// 老客户 end

@ -286,77 +286,82 @@ class MeetingData {
dataGHSales = async (param) => {
this.GHSalesLoading = true;
const salesParam = { ...param, DateType: 'confirmDate', WebCode: 'CHT,AH,GH,GHKYZG,GHKYHW,ZWQD', OrderType:'ALL', }; // WebCode: 不含分销
const partnerParam = { WebCode: 'GHTOBHW,GHTOBZG' };
const [
{ total1: CHSalesData }, // 不含分销
{ total1: AHSalesData }, // 不含分销
{ total1: GHSalesData }, // 不含分销
{ total1: partnerSalesData },
{ total1: totalSalesData },
{ total1: CHSalesDataTotal },
{ total1: CHPartnerSalesData },
{ total1: AHSalesDataTotal },
{ total1: AHpartnerSalesData },
{ total1: GHSalesDataTotal },
{ total1: GHpartnerSalesData },
] = 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',})
getDepartmentOrderMLByType({...salesParam, DepartmentList: '1,2', WebCode: 'ALL', }),
getDepartmentOrderMLByType({...salesParam, DepartmentList: '1,2', ...partnerParam }),
getDepartmentOrderMLByType({...salesParam, DepartmentList: '28', WebCode: 'ALL', }),
getDepartmentOrderMLByType({...salesParam, DepartmentList: '28', ...partnerParam }),
getDepartmentOrderMLByType({...salesParam, DepartmentList: '33', WebCode: 'ALL', }),
getDepartmentOrderMLByType({...salesParam, DepartmentList: '33', ...partnerParam }),
]);
// 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 CHSalesData = {'COLI_CJCount': CHSalesDataTotal.COLI_CJCount-CHPartnerSalesData.COLI_CJCount, 'COLI_ML2': CHSalesDataTotal.COLI_ML2-CHPartnerSalesData.COLI_ML2};
const AHSalesData = {'COLI_CJCount': AHSalesDataTotal.COLI_CJCount-AHpartnerSalesData.COLI_CJCount, 'COLI_ML2': AHSalesDataTotal.COLI_ML2-AHpartnerSalesData.COLI_ML2};
const GHSalesData = {'COLI_CJCount': GHSalesDataTotal.COLI_CJCount-GHpartnerSalesData.COLI_CJCount, 'COLI_ML2': GHSalesDataTotal.COLI_ML2-GHpartnerSalesData.COLI_ML2};
const partnerSalesData = {'COLI_CJCount': CHPartnerSalesData.COLI_CJCount+AHpartnerSalesData.COLI_CJCount, 'COLI_ML2': CHPartnerSalesData.COLI_ML2+AHpartnerSalesData.COLI_ML2};
const totalSalesData = {
'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 },
{ total1: CHSalesYearTotal },
{ total1: CHPartnerSalesYear },
{ total1: AHSalesYearTotal },
{ total1: AHpartnerSalesYear },
{ total1: GHSalesYearTotal },
{ total1: GHpartnerSalesYear },
] = 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',})
getDepartmentOrderMLByType({...salesParam, Date1: yearStart, DepartmentList: '1,2', WebCode: 'ALL', }),
getDepartmentOrderMLByType({...salesParam, Date1: yearStart, DepartmentList: '1,2', ...partnerParam }),
getDepartmentOrderMLByType({...salesParam, Date1: yearStart, DepartmentList: '28', WebCode: 'ALL', }),
getDepartmentOrderMLByType({...salesParam, Date1: yearStart, DepartmentList: '28', ...partnerParam }),
getDepartmentOrderMLByType({...salesParam, Date1: yearStart, DepartmentList: '33', WebCode: 'ALL', }),
getDepartmentOrderMLByType({...salesParam, Date1: yearStart, DepartmentList: '33', ...partnerParam }),
]);
// 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 CHDataYear = {'COLI_CJCount': CHSalesYearTotal.COLI_CJCount-CHPartnerSalesYear.COLI_CJCount, 'COLI_ML2': CHSalesYearTotal.COLI_ML2-CHPartnerSalesYear.COLI_ML2};
const AHDataYear = {'COLI_CJCount': AHSalesYearTotal.COLI_CJCount-AHpartnerSalesYear.COLI_CJCount, 'COLI_ML2': AHSalesYearTotal.COLI_ML2-AHpartnerSalesYear.COLI_ML2};
const GHDataYear = {'COLI_CJCount': GHSalesYearTotal.COLI_CJCount-GHpartnerSalesYear.COLI_CJCount, 'COLI_ML2': GHSalesYearTotal.COLI_ML2-GHpartnerSalesYear.COLI_ML2};
const partnerDataYear = {'COLI_CJCount': CHPartnerSalesYear.COLI_CJCount+AHpartnerSalesYear.COLI_CJCount, 'COLI_ML2': CHPartnerSalesYear.COLI_ML2+AHpartnerSalesYear.COLI_ML2};
const totalDataYear = {
'COLI_CJCount': CHSalesYearTotal.COLI_CJCount + AHSalesYearTotal.COLI_CJCount + GHSalesYearTotal.COLI_CJCount,
'COLI_ML2': CHSalesYearTotal.COLI_ML2 + AHSalesYearTotal.COLI_ML2 + GHSalesYearTotal.COLI_ML2,
};
/** 截至今年 - 走团 */
const [
{ total1: CHStartDataYear },
{ total1: AHStartDataYear },
{ total1: GHStartDataYear },
{ total1: partnerStartDataYear },
{ total1: totalStartDataYear },
{ total1: CHStartDataYearTotal },
{ total1: CHPartnerStartDataYear },
{ total1: AHStartDataYearTotal },
{ total1: AHpartnerStartDataYear },
{ total1: GHStartDataYearTotal },
{ total1: GHpartnerStartDataYear },
] = await Promise.all([
getDepartmentOrderMLByType({...salesParam, Date1: yearStart, Date2:yearEnd, DepartmentList: '1,2', DateType: 'startDate' }),
getDepartmentOrderMLByType({...salesParam, Date1: yearStart, Date2:yearEnd, DepartmentList: '28', DateType: 'startDate' }),
getDepartmentOrderMLByType({...salesParam, Date1: yearStart, Date2:yearEnd, DepartmentList: '33', DateType: 'startDate' }),
/** 截至今年 - 走团 - 分销 */
getDepartmentOrderMLByType({...salesParam, Date1: yearStart, Date2:yearEnd, DepartmentList: '1,2,28,7,33',WebCode: 'GHTOBHW,GHTOBZG', DateType: 'startDate',}),
getDepartmentOrderMLByType({...salesParam, Date1: yearStart, Date2:yearEnd, DepartmentList: '1,2,28,7,33',WebCode: 'ALL', DateType: 'startDate',})
getDepartmentOrderMLByType({...salesParam, Date1: yearStart, Date2:yearEnd, DateType: 'startDate', DepartmentList: '1,2', WebCode: 'ALL', }),
getDepartmentOrderMLByType({...salesParam, Date1: yearStart, Date2:yearEnd, DateType: 'startDate', DepartmentList: '1,2', ...partnerParam }),
getDepartmentOrderMLByType({...salesParam, Date1: yearStart, Date2:yearEnd, DateType: 'startDate', DepartmentList: '28', WebCode: 'ALL', }),
getDepartmentOrderMLByType({...salesParam, Date1: yearStart, Date2:yearEnd, DateType: 'startDate', DepartmentList: '28', ...partnerParam }),
getDepartmentOrderMLByType({...salesParam, Date1: yearStart, Date2:yearEnd, DateType: 'startDate', DepartmentList: '33', WebCode: 'ALL', }),
getDepartmentOrderMLByType({...salesParam, Date1: yearStart, Date2:yearEnd, DateType: 'startDate', DepartmentList: '33', ...partnerParam }),
]);
// 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 CHStartDataYear = {'COLI_CJCount': CHStartDataYearTotal.COLI_CJCount-CHPartnerStartDataYear.COLI_CJCount, 'COLI_ML2': CHStartDataYearTotal.COLI_ML2-CHPartnerStartDataYear.COLI_ML2};
const AHStartDataYear = {'COLI_CJCount': AHStartDataYearTotal.COLI_CJCount-AHpartnerStartDataYear.COLI_CJCount, 'COLI_ML2': AHStartDataYearTotal.COLI_ML2-AHpartnerStartDataYear.COLI_ML2};
const GHStartDataYear = {'COLI_CJCount': GHStartDataYearTotal.COLI_CJCount-GHpartnerStartDataYear.COLI_CJCount, 'COLI_ML2': GHStartDataYearTotal.COLI_ML2-GHpartnerStartDataYear.COLI_ML2};
const partnerStartDataYear = {'COLI_CJCount': CHPartnerStartDataYear.COLI_CJCount+AHpartnerStartDataYear.COLI_CJCount, 'COLI_ML2': CHPartnerStartDataYear.COLI_ML2+AHpartnerStartDataYear.COLI_ML2};
const totalStartDataYear = {
'COLI_CJCount': CHStartDataYearTotal.COLI_CJCount + AHStartDataYearTotal.COLI_CJCount + GHStartDataYearTotal.COLI_CJCount,
'COLI_ML2': CHStartDataYearTotal.COLI_ML2 + AHStartDataYearTotal.COLI_ML2 + GHStartDataYearTotal.COLI_ML2,
};
const rows = [
{

@ -1,6 +1,6 @@
import { makeAutoObservable, runInAction, toJS } from 'mobx';
import { fetchJSON } from '../utils/request';
import { isEmpty, sortDescBy, objectMapper, groupBy, pick, unique } from '../utils/commons';
import { isEmpty, sortDescBy, objectMapper, groupBy, pick, unique, cloneDeep } from '../utils/commons';
import { groupsMappedByCode, dataFieldAlias } from './../libs/ht';
import { DATE_FORMAT, SMALL_DATETIME_FORMAT } from './../config';
import moment from 'moment';
@ -19,6 +19,20 @@ const fetchResultsData = async (param) => {
return json.errcode === 0 ? json.result : [];
};
const fetchProcessData = async (param) => {
const defaultParam = {
WebCode: 'All',
DepartmentList: '',
opisn: -1,
Date1: '',
Date2: '',
groupType: '',
groupDateType: '',
};
const json = await fetchJSON('/service-Analyse2/sales_crm_process', { ...defaultParam, ...param });
return json.errcode === 0 ? json.result : [];
};
class SalesCRMData {
constructor(appStore) {
this.appStore = appStore;
@ -30,17 +44,11 @@ class SalesCRMData {
const retKey = param.groupDateType === '' ? (param.groupType === 'overview' ? 'dataSource' : 'details') : 'byDate';
this.results.loading = true;
const date90={
Date1: moment().subtract(90, 'days').format(DATE_FORMAT),
Date2: moment().subtract(30, 'days').format(SMALL_DATETIME_FORMAT),
};
const date180={
Date1: moment().subtract(180, 'days').format(DATE_FORMAT),
Date2: moment().subtract(50, 'days').format(SMALL_DATETIME_FORMAT),
};
const date90=this.searchValues.date90;
const date180=this.searchValues.date180;
const [result90, result180] = await Promise.all([
fetchResultsData({ ...this.searchValues, ...date90, ...param }),
fetchResultsData({ ...this.searchValues, ...date180, ...param }),
fetchResultsData({ ...this.searchValuesToSub, ...date90, ...param }),
fetchResultsData({ ...this.searchValuesToSub, ...date180, ...param }),
]);
const _90O = groupBy(result90, 'groupsKey');
const _180O = groupBy(result180, 'groupsKey');
@ -63,12 +71,11 @@ class SalesCRMData {
return this.results;
}
async getResultData(param = {}) {
const retKey = param.groupDateType === '' ? 'byOperator' : 'byDate';
this.results.loading = true;
this.results[retKey] = [];
const res = await fetchResultsData({ ...this.searchValues, ...param });
const res = await fetchResultsData({ ...this.searchValuesToSub, ...param });
runInAction(() => {
this.results.loading = false;
this.results[retKey] = retKey === 'byOperator' ? res.filter(ele => ele.SumML > 0).sort(sortDescBy('SumML')) : res;
@ -76,23 +83,56 @@ class SalesCRMData {
return this.results;
};
async getProcessData(param = {}) {
// const retKey = param.groupDateType === '' ? 'byOperator' : 'byDate';
const retKey = param.groupDateType === '' ? (param.groupType !== 'operator' ? 'dataSource' : 'details') : 'byDate';
this.process.loading = true;
this.process[retKey] = [];
const res = await fetchProcessData({ ...this.searchValuesToSub, ...param });
runInAction(() => {
this.process.loading = false;
this.process[retKey] = [].concat(this.process[retKey], res);
// this.process[retKey] =retKey === 'byOperator' ? res.filter(ele => ele.)
});
}
searchValues = {
// DateType: { key: 'confirmDate', label: '确认日期'},
date: moment(),
DateType: { key: 'applyDate', label: '提交日期'},
WebCode: { key: 'All', label: '所有来源' },
// IncludeTickets: { key: '1', label: '含门票'},
DepartmentList: [groupsMappedByCode.GH], // test: GH
DepartmentList: [groupsMappedByCode.GH],
operator: '-1',
opisn: '-1',
date90: {
Date1: moment().subtract(90, 'days').format(DATE_FORMAT),
Date2: moment().subtract(30, 'days').format(SMALL_DATETIME_FORMAT),
},
date180: {
Date1: moment().subtract(180, 'days').format(DATE_FORMAT),
Date2: moment().subtract(50, 'days').format(SMALL_DATETIME_FORMAT),
}
};
searchValuesToSub = {};
setSearchValues(obj, values) {
this.searchValues = { ...this.searchValues, ...values };
if (values.date) {
this.searchValues.date90 = {
Date1: (values.date.clone()).subtract(90, 'days').format(DATE_FORMAT),
Date2: (values.date.clone()).subtract(30, 'days').format(SMALL_DATETIME_FORMAT),
};
this.searchValues.date180 = {
Date1: (values.date.clone()).subtract(180, 'days').format(DATE_FORMAT),
Date2: (values.date.clone()).subtract(50, 'days').format(SMALL_DATETIME_FORMAT),
};
}
this.searchValuesToSub = obj;
}
results = { loading: false, dataSource: [], details: [], byDate: [], byOperator: [] };
process = { loading: false, dataSource: [], details: [], byDate: [], byOperator: [] };
resetData = () => {
this.results.loading = false;
for (const key of Object.keys(this.results)) {
@ -100,6 +140,11 @@ class SalesCRMData {
this.results[key] = [];
}
}
for (const key of Object.keys(this.process)) {
if (key !== 'loading') {
this.process[key] = [];
}
}
};
}
export default SalesCRMData;

@ -28,12 +28,12 @@ const AgentGroupCount = () => {
...date_picker_store.formValues,
...customerServicesStore.searchValues,
},
shows: ['agency', 'DateType', 'DepartmentList', 'countryArea', 'dates'],
shows: ['agency', 'departureDateType', 'DepartmentList', 'countryArea', 'dates'],
fieldProps: {
DepartmentList: { show_all: true, mode: 'multiple' },
WebCode: { show_all: false, mode: 'multiple' },
dates: { hide_vs: true },
DateType: { disabledKeys: ['applyDate'] },
departureDateType: { disabledKeys: ['applyDate'] },
},
}}
onSubmit={(_err, obj, form) => {
@ -46,6 +46,9 @@ const AgentGroupCount = () => {
<Row>
<Col span={24}>
<Typography.Title level={3}>地接社团信息</Typography.Title>
<Divider orientation="right" plain>
<TableExportBtn label={'地接社团信息'} {...{ columns: agentGroupListColumns, dataSource: agentGroupList }} />
</Divider>
<Table
sticky
id="agentGroupList"
@ -57,9 +60,6 @@ const AgentGroupCount = () => {
pagination={false}
scroll={{ x: 1000 }}
/>
<Divider orientation="right" plain>
<TableExportBtn label={'地接社团信息'} {...{ columns: agentGroupListColumns, dataSource: agentGroupList }} />
</Divider>
</Col>
</Row>
</Space>

@ -32,12 +32,12 @@ const AgentGroupList = () => {
...date_picker_store.formValues,
...customerServicesStore.searchValues,
},
shows: ['DateType', 'DepartmentList', 'dates'],
shows: ['departureDateType', 'DepartmentList', 'dates'],
fieldProps: {
DepartmentList: { show_all: true },
WebCode: { show_all: false, mode: 'multiple' },
dates: { hide_vs: true },
DateType: { disabledKeys: ['applyDate'] },
departureDateType: { disabledKeys: ['applyDate'] },
},
}}
onSubmit={(_err, obj, form, str) => {

@ -26,15 +26,18 @@ const filterFields = [
{ key: 'IsOld_txt', label: '是否老客户' },
{ key: 'isCusCommend_txt', label: '是否老客户推荐' },
{ key: 'hasOld_txt', label: '老客户(推荐)' },
{ key: 'HotelStar', label: '酒店星级' },
{ key: 'destinationCountry_AsJOSN', label: '目的地国籍' },
{ key: 'PPPriceRange', label: '人均天/单区间(外币)' },
{ key: 'destinations_AsJOSN', label: '目的地城市' },
{ key: 'RTXF_WB_range', label: '人天消费(外币)' },
{ key: 'PPPriceRange', label: '人均天/单(外币)' },
// { key: 'unitPPPriceRange', label: '()' },
// todo: , ,
{ key: 'SumML_ctxt1', label: '毛利范围[1W]' },
{ key: 'SumML_ctxt1_5', label: '毛利范围[1.5W]' },
{ key: 'SumML_ctxt2', label: '毛利范围[2W]' },
{ key: 'SumML_ctxt3', label: '毛利范围[3W]' },
{ key: 'SumML_ctxt4', label: '毛利范围[4W]' },
// { key: 'SumML_ctxt1', label: '[1W]' },
// { key: 'SumML_ctxt1_5', label: '[1.5W]' },
// { key: 'SumML_ctxt2', label: '[2W]' },
// { key: 'SumML_ctxt3', label: '[3W]' },
// { key: 'SumML_ctxt4', label: '[4W]' },
{ key: 'SumML_ctxt', label: '毛利' },
];
const filterFieldsMapped = filterFields.reduce((r, v) => ({ ...r, [v.key]: v }), {});
@ -706,6 +709,7 @@ export default observer((props) => {
/>
</Spin>
</section>
{ !pivotDateColumns[0].includes('destinationCountry_AsJOSN') && !pivotDateColumns[0].includes('destinations_AsJOSN') &&
<section>
<Spin spinning={loading}>
<h3>
@ -721,6 +725,7 @@ export default observer((props) => {
<Table {...detailsTableProps} dataSource={pivotRowDataSource} components={{ body: { cell: TdCell } }} />
</Spin>
</section>
}
</div>
);
});

@ -25,13 +25,13 @@ const DestinationGroupCount = () => {
countryArea: { key: 'china', label: '国内' },
...customerServicesStore.searchValues,
},
shows: ['DateType', 'DepartmentList', 'countryArea', 'orderStatus', 'dates'],
shows: ['departureDateType', 'DepartmentList', 'countryArea', 'orderStatus', 'dates'],
fieldProps: {
DepartmentList: { show_all: true, mode: 'multiple' },
orderStatus: { show_all: true },
countryArea: { show_all: false },
dates: { hide_vs: true },
DateType: { disabledKeys: ['applyDate'] },
departureDateType: { disabledKeys: ['applyDate'] },
},
}}
onSubmit={(_err, obj, form) => {
@ -44,6 +44,9 @@ const DestinationGroupCount = () => {
<Row>
<Col span={24}>
<Typography.Title level={3}>目的地团信息</Typography.Title>
<Divider orientation="right" plain>
<TableExportBtn label={'目的地团信息'} {...{ columns: destinationGroupCountColumns, dataSource: destinationGroupCount }} />
</Divider>
<Table
sticky
id="destinationGroupCount"
@ -55,9 +58,6 @@ const DestinationGroupCount = () => {
pagination={false}
scroll={{ x: 1000 }}
/>
<Divider orientation="right" plain>
<TableExportBtn label={'目的地团信息'} {...{ columns: destinationGroupCountColumns, dataSource: destinationGroupCount }} />
</Divider>
</Col>
</Row>
</Space>

@ -33,13 +33,13 @@ const DestinationGroupList = () => {
countryArea: { key: 'china', label: '国内' },
...customerServicesStore.searchValues,
},
shows: ['DateType', 'DepartmentList', 'dates'],
shows: ['departureDateType', 'DepartmentList', 'dates'],
fieldProps: {
DepartmentList: { show_all: true },
orderStatus: { show_all: true },
countryArea: { show_all: false },
dates: { hide_vs: true },
DateType: { disabledKeys: ['applyDate'] },
departureDateType: { disabledKeys: ['applyDate'] },
},
}}
onSubmit={(_err, obj, form) => {

@ -83,21 +83,15 @@ export default observer(() => {
dataIndex: 'SumOrder',
render: (v, r) => (
<>
<Row align={'middle'}>
<Col flex={"100px"}>
<Text strong>{v}</Text>
</Col>
<Col flex={'auto'}>
<Space direction={'vertical'}>
<span>
<Text strong>{v}</Text>
<span>
<span>同比: </span> <VSTag diffPercent={r.SumOrderToY} diffData={r.SumOrderDiffY} />
</span>
<span>
<span>环比: </span> <VSTag diffPercent={r.SumOrderToQ} diffData={r.SumOrderDiffQ} />
</span>
</Space>
</Col>
</Row>
</>
),
},
@ -106,21 +100,15 @@ export default observer(() => {
dataIndex: 'ConfirmOrder',
render: (v, r) => (
<>
<Row align={'middle'}>
<Col flex={"100px"}>
<Text strong>{v}</Text>
</Col>
<Col flex={'auto'}>
<Space direction={'vertical'}>
<span>
<Text strong>{v}</Text>
<span>
<span>同比: </span> <VSTag diffPercent={r.ConfirmOrderToY} diffData={r.ConfirmOrderDiffY} />
</span>
<span>
<span>环比: </span> <VSTag diffPercent={r.ConfirmOrderToQ} diffData={r.ConfirmOrderDiffQ} />
</span>
</Space>
</Col>
</Row>
</>
),
},
@ -129,21 +117,15 @@ export default observer(() => {
dataIndex: 'SumML',
render: (v, r) => (
<>
<Row align={'middle'}>
<Col flex={"150px"}>
<Text strong>{dataFieldAlias.SumML.formatter(v)}</Text>
</Col>
<Col flex={'auto'}>
<Space direction={'vertical'}>
<span>
<Text strong>{dataFieldAlias.SumML.formatter(v)}</Text>
<span>
<span>同比: </span> <VSTag diffPercent={r.SumMLToY} diffData={dataFieldAlias.SumML.formatter(r.SumMLDiffY)} />
</span>
<span>
<span>环比: </span> <VSTag diffPercent={r.SumMLToQ} diffData={dataFieldAlias.SumML.formatter(r.SumMLDiffQ)} />
</span>
</Space>
</Col>
</Row>
</>
),
},

@ -1,85 +0,0 @@
import React, { Children, useContext, useState } from 'react';
import { observer } from 'mobx-react';
import { stores_Context } from '../config';
import moment from 'moment';
import { SlackOutlined, SketchOutlined, AntCloudOutlined, RedditOutlined, GithubOutlined } from '@ant-design/icons';
import { Row, Col, Table, Select, Space, Typography, Progress, Spin, Divider, Button, Switch } from 'antd';
import SearchForm from './../components/search/SearchForm';
export default observer((props) => {
const { sale_store, date_picker_store: searchFormStore } = useContext(stores_Context);
const { formValues, siderBroken } = searchFormStore;
const activityTableProps = {
columns: [
{ title: '', dataIndex: 'op', key: 'op' }, // :
{
title: '顾问动作',
key: 'date',
children: [
{ title: '首次响应率24H', dataIndex: 'action', key: 'action' },
{ title: '48H内报价率', dataIndex: 'action', key: 'action' },
{ title: '一次报价率', dataIndex: 'action', key: 'action' },
{ title: '二次报价率', dataIndex: 'action', key: 'action' },
{ title: '>50条会话', dataIndex: 'action', key: 'action' },
{ title: '违规数', dataIndex: 'action', key: 'action' },
],
},
{
title: '客人回复',
key: 'department',
children: [
{ title: '首次回复率24H', dataIndex: 'action', key: 'action' },
{ title: '48H内报价回复率', dataIndex: 'action', key: 'action' },
{ title: '一次报价回复率', dataIndex: 'action', key: 'action' },
{ title: '二次报价回复率', dataIndex: 'action', key: 'action' },
],
},
],
};
const riskTableProps = {
columns: [
{ title: '', dataIndex: 'date', key: 'date' }, //
{ title: '>24H回复', dataIndex: 'action', key: 'action' },
{ title: '首次报价周期>48h', dataIndex: 'action', key: 'action' },
{ title: '报价次数<1次', dataIndex: 'action' },
{ title: '报价次数<2次', dataIndex: 'action' },
],
};
return (
<>
<Row gutter={16} className={siderBroken ? '' : 'sticky-top'}>
<Col md={24} lg={24} xxl={24}>
<SearchForm
defaultValue={{
initialValue: {
...formValues,
...sale_store.searchValues,
},
shows: ['DepartmentList', 'WebCode', 'dates'],
fieldProps: {
DepartmentList: { show_all: false, mode: 'multiple', col: 5 },
WebCode: { show_all: false, mode: 'multiple', col: 5 },
dates: { hide_vs: true },
},
}}
onSubmit={(_err, obj, form, str) => {
sale_store.setSearchValues(obj, form);
// pageRefresh(obj);
}}
/>
</Col>
</Row>
<section>
<Table {...activityTableProps} bordered />
</section>
<section>
<h3>未成行订单</h3>
<Table {...riskTableProps} bordered />
</section>
</>
);
});

@ -10,6 +10,19 @@ import { cloneDeep, fixTo2Decimals, sortBy, isEmpty, pick } from '../utils/commo
import Column from '../components/Column';
import { groupsMappedByKey } from './../libs/ht';
const COLOR_SETS = [
"#FFFFFF",
// "#5B8FF9",
// "#FF6B3B",
"#9FB40F",
"#76523B",
"#DAD5B5",
"#E19348",
"#F383A2",
];
const transparentHex = '1A';
const numberConvert10K = (number, scale = 10) => {
return fixTo2Decimals((number/(1000*scale)));
};
@ -34,7 +47,7 @@ export default observer((props) => {
const separateParam = [];
if (includeCH) {
const inCH = deptList.filter(k => ['1', '2', '7'].includes(k)).join(',');
separateParam.push({ DepartmentList: inCH, retLabel: 'CH'});
separateParam.push({ DepartmentList: inCH, retLabel: 'CH'});
}
if (includeAH) {
separateParam.push({ DepartmentList: '28', retLabel: 'AH'});
@ -103,14 +116,17 @@ export default observer((props) => {
* 业绩数据列
* ! 成行率: CH个人成行率<12%, AH<8%
*/
const dataFields = (suffix) => [
const dataFields = (suffix, colRootIndex) => [
{
key: 'ConfirmRates' + suffix,
title: '成行率',
dataIndex: [suffix, 'ConfirmRates'],
width: '5em',
// CH<12%, AH<8%
render: (val, r) => ({ props: { style: { color: val < (retPropsMinRatesSet?.[r?.retProps || 'default'] || retPropsMinRatesSet.default) ? 'red' : 'green' } }, children: val ? `${val}%` : '' }),
render: (val, r) => ({
props: { style: { color: val < (retPropsMinRatesSet?.[r?.retProps || 'default'] || retPropsMinRatesSet.default) ? 'red' : 'green', backgroundColor: COLOR_SETS[colRootIndex]+transparentHex } },
children: val ? `${val}%` : '',
}),
sorter: (a, b) => (a.groupType === 'overview' ? -1 : b.groupType === 'overview' ? 0 : a[suffix].ConfirmRates - b[suffix].ConfirmRates),
},
{
@ -118,7 +134,10 @@ export default observer((props) => {
title: '业绩/万',
dataIndex: [suffix, 'SumML'],
width: '5em',
render: (_, r) => numberConvert10K(_),
render: (_, r) => ({
props: { style: { backgroundColor: COLOR_SETS[colRootIndex]+transparentHex } },
children: numberConvert10K(_),
}),
sorter: (a, b) => (a.groupType === 'overview' ? -1 : b.groupType === 'overview' ? 0 : a[suffix].SumML - b[suffix].SumML),
},
{
@ -126,6 +145,10 @@ export default observer((props) => {
title: '团数',
dataIndex: [suffix, 'ConfirmOrder'],
width: '5em',
render: (_, r) => ({
props: { style: { backgroundColor: COLOR_SETS[colRootIndex]+transparentHex } },
children: _,
}),
sorter: (a, b) => (a.groupType === 'overview' ? -1 : b.groupType === 'overview' ? 0 : a[suffix].ConfirmOrder - b[suffix].ConfirmOrder),
},
{
@ -133,6 +156,10 @@ export default observer((props) => {
title: '订单数',
dataIndex: [suffix, 'SumOrder'],
width: '5em',
render: (_, r) => ({
props: { style: { backgroundColor: COLOR_SETS[colRootIndex]+transparentHex } },
children: _,
}),
sorter: (a, b) => (a.groupType === 'overview' ? -1 : b.groupType === 'overview' ? 0 : a[suffix].SumOrder - b[suffix].SumOrder),
},
{
@ -140,6 +167,10 @@ export default observer((props) => {
title: '老客户团数',
dataIndex: [suffix, 'ResumeOrder'],
width: '5em',
render: (_, r) => ({
props: { style: { backgroundColor: COLOR_SETS[colRootIndex]+transparentHex } },
children: _,
}),
sorter: (a, b) => (a.groupType === 'overview' ? -1 : b.groupType === 'overview' ? 0 : a[suffix].ResumeOrder - b[suffix].ResumeOrder),
},
{
@ -147,7 +178,10 @@ export default observer((props) => {
title: '老客户成行率',
dataIndex: [suffix, 'ResumeRates'],
width: '5em',
render: (val, r) => ({ children: val ? `${val}%` : '' }),
render: (val, r) => ({
props: { style: { backgroundColor: COLOR_SETS[colRootIndex]+transparentHex } },
children: val ? `${val}%` : ''
}),
sorter: (a, b) => (a.groupType === 'overview' ? -1 : b.groupType === 'overview' ? 0 : a[suffix].ResumeRates - b[suffix].ResumeRates),
},
];
@ -168,12 +202,12 @@ export default observer((props) => {
{
title: '前90 -30天',
key: 'date',
children: dataFields('result90'),
children: dataFields('result90', 0),
},
{
title: '前180 -50天',
key: 'department',
children: dataFields('result180'),
children: dataFields('result180', 1),
},
],
rowClassName: (record, rowIndex) => {
@ -231,7 +265,7 @@ export default observer((props) => {
...formValues,
...SalesCRMDataStore.searchValues,
},
shows: ['DepartmentList', 'WebCode'],
shows: ['DepartmentList', 'WebCode', 'date'],
fieldProps: {
DepartmentList: { show_all: false, mode: 'multiple', col: 5 },
WebCode: { show_all: false, mode: 'multiple', col: 5 },

@ -0,0 +1,257 @@
import React, { useContext } from 'react';
import { observer } from 'mobx-react';
import { stores_Context } from '../config';
import { InfoCircleOutlined } from '@ant-design/icons';
import { Row, Col, Table, Tooltip } from 'antd';
import SearchForm from '../components/search/SearchForm';
import { pick } from '../utils/commons';
const COLOR_SETS = [
"#FFFFFF",
// "#5B8FF9",
// "#FF6B3B",
"#9FB40F",
"#76523B",
"#DAD5B5",
"#E19348",
"#F383A2",
];
const transparentHex = '1A';
export default observer((props) => {
const { SalesCRMDataStore, date_picker_store: searchFormStore } = useContext(stores_Context);
// const { formValues, siderBroken } = searchFormStore;
const { formValues, formValuesToSub, siderBroken } = searchFormStore;
const _formValuesToSub = pick(formValuesToSub, ['DepartmentList', 'WebCode']);
const { resetData, process } = SalesCRMDataStore;
const operatorObjects = process.details.map((v) => ({ key: v.groupsKey, value: v.groupsKey, label: v.groupsLabel, text: v.groupsLabel }));
const pageRefresh = async (obj) => {
resetData();
Promise.allSettled([
SalesCRMDataStore.getProcessData({
...(obj || _formValuesToSub),
// ...subParam,
// groupType: 'overview',
groupType: 'dept',
groupDateType: '',
}),
SalesCRMDataStore.getProcessData({
...(obj || _formValuesToSub),
// ...subParam,
groupType: 'operator',
groupDateType: '',
}),
]);
};
const tableSorter = (a, b, colName) => (a.groupType !== 'operator' ? -1 : b.groupType !== 'operator' ? 0 : a[colName] - b[colName]);
const percentageRender = val => val ? `${val}%` : '';
const activityTableProps = {
rowKey: 'groupsKey',
pagination: { pageSize: 10, showSizeChanger: false },
size: 'small',
rowClassName: (record, rowIndex) => {
return record.groupType === 'operator' ? '': 'ant-tag-blue';
},
showSorterTooltip: false,
columns: [
{ title: '', dataIndex: 'groupsLabel', key: 'groupsLabel', width: '6rem',
filterSearch: true,
filters: operatorObjects.sort((a, b) => a.text.localeCompare(b.text)),
onFilter: (value, record) => record.groupsKey === value || record.groupType !== 'operator',
}, // :
{
title: '顾问动作',
key: 'date',
children: [
{ title: () => (
<>
首次响应率24H{' '}
<Tooltip title="达到24H内回复的订单数/总订单数">
<InfoCircleOutlined />
</Tooltip>
</>
), dataIndex: 'firstTouch24', key: 'firstTouch24', render: percentageRender,
sorter: (a, b) => tableSorter(a, b, 'firstTouch24'),
},
{ title: () => (
<>
48H内报价率{' '}
<Tooltip title="达到48H内报价的订单数/总订单数">
<InfoCircleOutlined />
</Tooltip>
</>
), dataIndex: 'firstQuote48', key: 'firstQuote48',render: percentageRender ,
sorter: (a, b) => tableSorter(a, b, 'firstQuote48'), },
{ title: () => (
<>
一次报价率{' '}
<Tooltip title="首次报价的订单数/总订单数">
<InfoCircleOutlined />
</Tooltip>
</>
), dataIndex: 'quote1', key: 'quote1',render: percentageRender ,
sorter: (a, b) => tableSorter(a, b, 'quote1'), },
{ title: () => (
<>
二次报价率{' '}
<Tooltip title="二次报价的订单数/一次报价后回复数">
<InfoCircleOutlined />
</Tooltip>
</>
), dataIndex: 'quote2', key: 'quote2',render: percentageRender ,
sorter: (a, b) => tableSorter(a, b, 'quote2'), },
{ title: () => (
<>
&gt;50条会话{' '}
<Tooltip title=">50条会话的订单数/总订单">
<InfoCircleOutlined />
</Tooltip>
</>
), dataIndex: 'turnsGT50', key: 'turnsGT50', render: percentageRender ,
sorter: (a, b) => tableSorter(a, b, 'turnsGT50'), },
{ title: () => (
<>
违规数{' '}
<Tooltip title="未遵循24H回复的订单数">
<InfoCircleOutlined />
</Tooltip>
</>
), dataIndex: 'violations', key: 'violations',
sorter: (a, b) => tableSorter(a, b, 'violations'), },
],
},
{
title: '客人回复',
key: 'department',
children: [
{
title: () => (
<>
首次回复率24H{' '}
<Tooltip title="达到24H内回复的订单数/总订单数">
<InfoCircleOutlined />
</Tooltip>
</>
), dataIndex: 'firstReply24', key: 'firstReply24',
render: (_, r) => ({
props: { style: { backgroundColor: COLOR_SETS[1]+transparentHex } },
children: percentageRender(_),
}),
sorter: (a, b) => tableSorter(a, b, 'firstReply24'), },
{
title: () => (
<>
48H内报价回复率{' '}
<Tooltip title="48H内报价后的回复数/报价的订单数">
<InfoCircleOutlined />
</Tooltip>
</>
), dataIndex: 'replyQuote48', key: 'replyQuote48',
render: (_, r) => ({
props: { style: { backgroundColor: COLOR_SETS[1]+transparentHex } },
children: percentageRender(_),
}),
sorter: (a, b) => tableSorter(a, b, 'replyQuote48'), },
{
title: () => (
<>
一次报价回复率{' '}
<Tooltip title="一次报价后回复率/订单总数">
<InfoCircleOutlined />
</Tooltip>
</>
), dataIndex: 'replyQuote1', key: 'replyQuote1',
render: (_, r) => ({
props: { style: { backgroundColor: COLOR_SETS[1]+transparentHex } },
children: percentageRender(_),
}),
sorter: (a, b) => tableSorter(a, b, 'replyQuote1'), },
{
title: () => (
<>
二次报价回复率{' '}
<Tooltip title="二次报价后回复数/一次报价后回复数">
<InfoCircleOutlined />
</Tooltip>
</>
), dataIndex: 'replyQuote2', key: 'replyQuote2',
render: (_, r) => ({
props: { style: { backgroundColor: COLOR_SETS[1]+transparentHex } },
children: percentageRender(_),
}),
sorter: (a, b) => tableSorter(a, b, 'replyQuote2'), },
],
},
],
};
const riskTableProps = {
rowKey: 'groupsKey',
pagination: { pageSize: 10, showSizeChanger: false },
size: 'small',
rowClassName: (record, rowIndex) => {
return record.groupType === 'operator' ? '': 'ant-tag-blue';
},
showSorterTooltip: false,
columns: [
{ title: '', dataIndex: 'groupsLabel', key: 'groupsLabel', width: '6rem',
filterSearch: true,
filters: operatorObjects.sort((a, b) => a.text.localeCompare(b.text)),
onFilter: (value, record) => record.groupsKey === value || record.groupType !== 'operator',
// render: (text, record) => { // todo:
// },
}, // :
{ title: '>24H回复', dataIndex: 'lostTouch24', key: 'lostTouch24',
sorter: (a, b) => tableSorter(a, b, 'lostTouch24'),
},
{ title: '首次报价周期>48h', dataIndex: 'lostQuote48', key: 'lostQuote48',
sorter: (a, b) => tableSorter(a, b, 'lostQuote48'),
},
{ title: '报价次数<1次', dataIndex: 'lostQuote1', key: 'lostQuote1',
sorter: (a, b) => tableSorter(a, b, 'lostQuote1'),
},
{ title: '报价次数<2次', dataIndex: 'lostQuote2', key: 'lostQuote2',
sorter: (a, b) => tableSorter(a, b, 'lostQuote2'),
},
],
};
return (
<>
<Row gutter={16} className={siderBroken ? '' : 'sticky-top'}>
<Col md={24} lg={24} xxl={24}>
<SearchForm
defaultValue={{
initialValue: {
...formValues,
...SalesCRMDataStore.searchValues,
},
shows: ['DepartmentList', 'WebCode', 'DateType', 'dates'],
fieldProps: {
DepartmentList: { show_all: false, mode: 'multiple', col: 5 },
WebCode: { show_all: false, mode: 'multiple', col: 5 },
dates: { hide_vs: true },
},
}}
onSubmit={(_err, obj, form, str) => {
SalesCRMDataStore.setSearchValues(obj, form);
pageRefresh(obj);
}}
/>
</Col>
</Row>
<section>
<Table {...activityTableProps} bordered dataSource={[...process.dataSource, ...process.details]} loading={process.loading} sticky />
</section>
<section>
<h3>未成行订单 数量</h3>
<Table {...riskTableProps} bordered dataSource={[...process.dataSource, ...process.details]} loading={process.loading} sticky />
</section>
</>
);
});

@ -1,6 +1,6 @@
import React, { Component } from "react";
import { Row, Col, Tabs, Table, Divider, Spin } from "antd";
import { ContainerOutlined, BlockOutlined, SmileOutlined, TagsOutlined, GlobalOutlined, FullscreenOutlined, DingtalkOutlined, CarryOutOutlined, CoffeeOutlined } from "@ant-design/icons";
import { ContainerOutlined, BlockOutlined, SmileOutlined, TagsOutlined, GlobalOutlined, FullscreenOutlined, DingtalkOutlined, CarryOutOutlined, CoffeeOutlined, ClockCircleOutlined, HeartOutlined, IdcardOutlined, ContactsOutlined } from "@ant-design/icons";
import { stores_Context } from "../config";
import { Line, Pie } from "@ant-design/charts";
import { observer } from "mobx-react";
@ -472,11 +472,14 @@ class Orders extends Component {
key: 'ToB',
label: (
<span>
<CoffeeOutlined />
<ContactsOutlined />
客运类别
</span>
),
},
{key: 'FoodRequirement',label: (<span><CoffeeOutlined />饮食要求</span>),},
{key: 'hobbies',label: (<span><HeartOutlined/>兴趣爱好</span>),},
{key: 'ages',label: (<span><IdcardOutlined/>年龄段</span>),},
].map((ele) => {
return {
...ele,

Loading…
Cancel
Save