feat: 客服: 酒店

main
Lei OT 2 months ago
parent 08aa01e33c
commit 17cedf14d9

@ -186,6 +186,21 @@ export default observer((props) => {
transform: (value) => value?.key || '', transform: (value) => value?.key || '',
default: '', default: '',
}, },
'hotelBookType': {
key: 'hotelBookType',
transform: (value) => value?.key || '',
default: '',
},
'hotelRecommandRate': {
key: 'hotelRecommandRate',
transform: (value) => value?.key || '',
default: '',
},
'hotelStar': {
key: 'hotelStar',
transform: (value) => value?.key || '',
default: '',
},
}; };
let dest = {}; let dest = {};
const { departureDateType, applyDate, applyDate2, year, yearDiff, dates, months, date, ...omittedValue } = values; const { departureDateType, applyDate, applyDate2, year, yearDiff, dates, months, date, ...omittedValue } = values;
@ -362,11 +377,11 @@ function getFields(props) {
item( item(
'countryArea', 'countryArea',
99, 99,
<Form.Item name={`countryArea`} initialValue={at(props, 'initialValue.countryArea')[0] || (fieldProps?.countryArea?.show_all ? { key: 'all', label: '所有国家' } : undefined)}> <Form.Item name={`countryArea`} initialValue={at(props, 'initialValue.countryArea')[0] || (fieldProps?.countryArea?.show_all ? { key: 'all', label: '国内外' } : undefined)}>
<Select style={{ width: '100%' }} placeholder="所有国家" labelInValue> <Select style={{ width: '100%' }} placeholder="国内外" labelInValue allowClear={fieldProps?.countryArea?.show_all || false}>
{fieldProps?.countryArea?.show_all && ( {fieldProps?.countryArea?.show_all && (
<Option key="all" value=""> <Option key="all" value="" disabled>
所有国家 国内外
</Option> </Option>
)} )}
<Option key="china" value="china"> <Option key="china" value="china">
@ -579,19 +594,19 @@ function getFields(props) {
fieldProps?.personRange?.col || 4 fieldProps?.personRange?.col || 4
), ),
item( item(
'bookType', 'hotelBookType',
99, 99,
<Form.Item name={`bookType`} initialValue={at(props, 'initialValue.bookType')[0] || (fieldProps?.bookType?.show_all ? { key: 'all', label: '预定类型' } : undefined)}> <Form.Item name={`hotelBookType`} initialValue={at(props, 'initialValue.hotelBookType')[0] || (fieldProps?.hotelBookType?.show_all ? { key: 'all', label: '预定类型' } : undefined)}>
<Select style={{ width: '100%' }} placeholder="预定类型" labelInValue allowClear> <Select style={{ width: '100%' }} placeholder="预定类型" labelInValue allowClear={fieldProps?.hotelBookType?.show_all || false}>
{fieldProps?.bookType?.show_all && ( {fieldProps?.hotelBookType?.show_all && (
<Option key="all" value=""> <Option key="all" value="" disabled>
所有 预定类型
</Option> </Option>
)} )}
<Option key="proxy" value="proxy"> <Option key="1" value="1">
代订 代订
</Option> </Option>
<Option key="direct" value="direct"> <Option key="0" value="0">
自订 自订
</Option> </Option>
</Select> </Select>
@ -599,18 +614,21 @@ function getFields(props) {
3 3
), ),
item( item(
'recommandRate', 'hotelRecommandRate',
99, 99,
<Form.Item name={`recommandRate`} initialValue={at(props, 'initialValue.recommandRate')[0] || (fieldProps?.recommandRate?.show_all ? { key: 'all', label: '推荐' } : undefined)}> <Form.Item name={`hotelRecommandRate`} initialValue={at(props, 'initialValue.hotelRecommandRate')[0] || (fieldProps?.hotelRecommandRate?.show_all ? { key: 'all', label: '推荐等级' } : undefined)}>
<Select style={{ width: '100%' }} placeholder="推荐" labelInValue allowClear> <Select style={{ width: '100%' }} placeholder="推荐等级" labelInValue allowClear={fieldProps?.hotelRecommandRate?.show_all || false}>
{fieldProps?.recommandRate?.show_all && ( {fieldProps?.hotelRecommandRate?.show_all && (
<Option key="all" value=""> <Option key="all" value="" disabled>
所有 推荐等级
</Option> </Option>
)} )}
<Option key="proxy" value="proxy"> <Option key="1" value="1">
主推 主推
</Option> </Option>
<Option key="0" value="0">
非主推
</Option>
</Select> </Select>
</Form.Item>, </Form.Item>,
3 3

@ -185,19 +185,16 @@ export const KPISubjects = [
]; ];
export const HotelStars = [ export const HotelStars = [
{ key: '5', value: '5', label: '5星' }, { key: '1', value: '1', label: '五星' },
{ key: '4', value: '4', label: '4星' }, { key: '2', value: '2', label: '四星' },
{ key: '3', value: '3', label: '3星' }, { key: '3', value: '3', label: '三星' },
{ key: '2', value: '2', label: '2星' }, { key: '4', value: '4', label: '二星' },
{ key: 'intl', value: 'intl', label: '国际社' }, { key: '8', value: '8', label: '准五星 ' },
{ key: 'internal', value: 'internal', label: '国内社' }, { key: '9', value: '9', label: '准四星' },
{ key: 'other', value: 'other', label: '其它' }, { key: '10', value: '10', label: '客栈' },
{ key: 'f5', value: 'f5', label: '准5星' }, { key: '11', value: '11', label: '公寓' },
{ key: 'f4', value: 'f4', label: '准4星' }, { key: '12', value: '12', label: '四合院酒店' },
{ key: 'inn', value: 'inn', label: '客栈' }, { key: '13', value: '13', label: '豪华五星' },
{ key: 'apartment', value: 'apartment', label: '公寓' },
{ key: 'siheyuan', value: 'siheyuan', label: '四合院酒店' },
{ key: 'luxury5', value: 'luxury5', label: '豪华五星' },
]; ];
/** /**

@ -7,24 +7,25 @@ import moment from 'moment';
const fetchHotelData = async (param) => { const fetchHotelData = async (param) => {
const defaultParam = { const defaultParam = {
DEI_SN:'', DEI_SN: '',
City:'', City: '',
OrderState:'', OrderState: '',
BookingType:'-1', BookingType: '-1',
RecommendedLevel:'-1', RecommendedLevel: '-1',
Star:'-1', Star: '-1',
ArriveDateCheck:'0', ArriveDateCheck: '0',
ArriveDateStart:'', ArriveDateStart: '',
ArriveDateEnd:'', ArriveDateEnd: '',
ConfirmDateCheck:'0', ConfirmDateCheck: '0',
ConfirmDateStart:'', ConfirmDateStart: '',
ConfirmDateEnd:'', ConfirmDateEnd: '',
Compare:'0', Compare: '0',
CompareDateStart:'', CompareDateStart: '',
CompareDateEnd:'', CompareDateEnd: '',
Area: '-1',
}; };
const json = await fetchJSON('/service-Analyse2/HotelReservation', { ...defaultParam, ...param }); const json = await fetchJSON('/service-Analyse2/HotelReservation', { ...defaultParam, ...param });
return json.errcode === 0 ? json.result : []; return json.errcode === 0 ? json.result || [] : [];
}; };
const fetchCruiseData = async (param) => { const fetchCruiseData = async (param) => {
@ -47,21 +48,27 @@ const fetchCruiseData = async (param) => {
Country: '-1', Country: '-1',
}; };
const json = await fetchJSON('/service-Analyse2/CruiseReservation', { ...defaultParam, ...param }); const json = await fetchJSON('/service-Analyse2/CruiseReservation', { ...defaultParam, ...param });
return json.errcode === 0 ? json.result : []; return json.errcode === 0 ? json.result || [] : [];
}; };
const keyMapped = { const paramKeyMapped = {
'applyDate': { key: '' }, 'DateType': [
'startDate': { key: 'ArriveDateCheck'}, { key: 'ArriveDateCheck', transform: (val) => (val === 'startDate' ? '1' : '0') },
'comfirmDate': { key: 'ConfirmDateCheck'}, { key: 'ConfirmDateCheck', transform: (val) => (val === 'confirmDate' ? '1' : '0') },
// { key: 'ApplyDateCheck', transform: (val) => (val === 'applyDate' ? '1' : '0') },
],
'DepartmentList': { key: 'DEI_SN' }, 'DepartmentList': { key: 'DEI_SN' },
'orderStatus': { key: 'OrderState' }, 'orderStatus': { key: 'OrderState' },
'Date1': { key: 'ArriveDateStart' }, 'Date1': [{ key: 'ArriveDateStart' }, { key: 'ConfirmDateStart' }],
'Date2': { key: 'ArriveDateEnd' }, 'Date2': [{ key: 'ArriveDateEnd' }, { key: 'ConfirmDateEnd' }],
'DateDiff1': { key: 'CompareDateStart' }, 'DateDiff1': { key: 'CompareDateStart' },
'DateDiff2': { key: 'CompareDateEnd' }, 'DateDiff2': { key: 'CompareDateEnd' },
'keyword': { key: 'ProductName' }, 'keyword': { key: 'ProductName' },
'cruiseDirection': { key: 'Direction' }, 'cruiseDirection': { key: 'Direction' },
'hotelStar': { key: 'Star' },
'hotelRecommandRate': { key: 'RecommendedLevel' },
'hotelBookType': { key: 'BookingType' },
'countryArea': { key: 'Area', transform: (val) => (val === 'china' ? '1' : val === 'foreign' ? '0' : '-1') },
}; };
class HotelCruise { class HotelCruise {
@ -73,16 +80,7 @@ class HotelCruise {
async getCruiseData(param = {}) { async getCruiseData(param = {}) {
this.cruise.loading = true; this.cruise.loading = true;
this.cruise.dataSource = []; this.cruise.dataSource = [];
const _queryParam = objectMapper(param, { const _queryParam = objectMapper(param, paramKeyMapped);
'DepartmentList': { key: 'DEI_SN' },
'orderStatus': { key: 'OrderState' },
'Date1': { key: 'ArriveDateStart' },
'Date2': { key: 'ArriveDateEnd' },
'DateDiff1': { key: 'CompareDateStart' },
'DateDiff2': { key: 'CompareDateEnd' },
'keyword': { key: 'ProductName' },
'cruiseDirection': { key: 'Direction' },
});
const queryParam = omit({ ...this.searchValuesToSub, ..._queryParam }, ['DepartmentList', 'orderStatus', 'keyword', 'Date1', 'Date2', 'DateDiff1', 'DateDiff2', 'cruiseDirection']); const queryParam = omit({ ...this.searchValuesToSub, ..._queryParam }, ['DepartmentList', 'orderStatus', 'keyword', 'Date1', 'Date2', 'DateDiff1', 'DateDiff2', 'cruiseDirection']);
queryParam.Compare = isEmpty(param.DateDiff1) ? '' : '1'; queryParam.Compare = isEmpty(param.DateDiff1) ? '' : '1';
const res = await fetchCruiseData(queryParam); const res = await fetchCruiseData(queryParam);
@ -104,16 +102,34 @@ class HotelCruise {
async getHotelData(param = {}) { async getHotelData(param = {}) {
this.hotel.loading = true; this.hotel.loading = true;
this.hotel.dataSource = []; this.hotel.dataSource = [];
const res = await fetchHotelData({ ...this.searchValuesToSub, ...param }); const _queryParam = objectMapper(param, paramKeyMapped);
const queryParam = omit({ ...this.searchValuesToSub, ..._queryParam }, [
'DepartmentList','orderStatus','keyword','Date1','Date2','DateDiff1','DateDiff2','DateType',
'hotelStar','hotelRecommandRate','hotelBookType','countryArea',
]);
queryParam.Compare = isEmpty(param.DateDiff1) ? '0' : '1';
const _res = await fetchHotelData(queryParam);
const res = (_res || []).map((ele) => ({ ...ele, RecommendRate_100: fixTo2Decimals(ele.RecommendRate * 100) + '%' }));
const resCP =
queryParam.Compare === '0'
? res
: (res || []).map((ele) => ({
...ele,
TotalNumPercent: ele.CPTotalNum ? fixTo2Decimals(((ele.TotalNum - ele.CPTotalNum) / ele.CPTotalNum) * 100) : '-',
RecomendNumPercent: ele.CPRecomendNum ? fixTo2Decimals(((ele.RecomendNum - ele.CPRecomendNum) / ele.CPRecomendNum) * 100) : '-',
RecommendRateDelta: fixTo2Decimals((ele.RecommendRate - (ele.CPRecommendRate || 0)) * 100),
CPRecommendRate_100: fixTo2Decimals(ele.CPRecommendRate * 100) + '%',
}));
console.log(resCP);
runInAction(() => { runInAction(() => {
this.hotel.loading = false; this.hotel.loading = false;
this.hotel.dataSource = [].concat(this.hotel.dataSource, res); this.hotel.dataSource = resCP;
}); });
} }
searchValues = { searchValues = {
date: moment(), date: moment(),
DateType: { key: 'applyDate', label: '提交日期' }, DateType: { key: 'confirmDate', label: '确认日期' },
WebCode: { key: '', label: '所有来源' }, WebCode: { key: '', label: '所有来源' },
// IncludeTickets: { key: '1', label: '含门票'}, // IncludeTickets: { key: '1', label: '含门票'},
DepartmentList: [{ key: '', label: '所有小组' }], DepartmentList: [{ key: '', label: '所有小组' }],

@ -15,6 +15,7 @@ export default observer((props) => {
const { formValues, siderBroken } = searchFormStore; const { formValues, siderBroken } = searchFormStore;
const tableSorter = (a, b, colName) => (a[colName] - b[colName]);
const tableProps = { const tableProps = {
size: 'small', size: 'small',
bordered: true, pagination: false, bordered: true, pagination: false,
@ -24,6 +25,7 @@ export default observer((props) => {
title: '房间数', title: '房间数',
dataIndex: 'TotalNum', dataIndex: 'TotalNum',
key: 'TotalNum', key: 'TotalNum',
sorter: (a, b) => tableSorter(a, b, 'TotalNum'),
render: (v, r) => ( render: (v, r) => (
<> <>
<Space direction={'vertical'}> <Space direction={'vertical'}>
@ -38,6 +40,7 @@ export default observer((props) => {
}, },
{ title: '人数', dataIndex: 'TotalPersonNum', key: 'TotalPersonNum' }, { title: '人数', dataIndex: 'TotalPersonNum', key: 'TotalPersonNum' },
{ title: '总利润', dataIndex: 'TotalProfit', key: 'TotalProfit', { title: '总利润', dataIndex: 'TotalProfit', key: 'TotalProfit',
sorter: (a, b) => tableSorter(a, b, 'TotalProfit'),
render: (v, r) => ( render: (v, r) => (
<> <>
<Space direction={'vertical'}> <Space direction={'vertical'}>

@ -1,22 +1,76 @@
import React, { useContext } from 'react'; import React, { useContext } from 'react';
import { observer } from 'mobx-react'; import { observer } from 'mobx-react';
import { stores_Context } from '../config'; import { stores_Context } from '../config';
import { Row, Col, Table } from 'antd'; import { Row, Col, Table, Space, Typography } from 'antd';
import SearchForm from './../components/search/SearchForm'; import SearchForm from './../components/search/SearchForm';
import { VSTag, TableExportBtn } from './../components/Data';
const { Text } = Typography;
export default observer((props) => { export default observer((props) => {
const { sale_store, date_picker_store: searchFormStore } = useContext(stores_Context); const { sale_store, date_picker_store: searchFormStore } = useContext(stores_Context);
const { customerServicesStore, date_picker_store } = useContext(stores_Context); const { customerServicesStore, date_picker_store, HotelCruiseStore } = useContext(stores_Context);
const { loading, dataSource } = HotelCruiseStore.hotel;
const { formValues, siderBroken } = searchFormStore; const { formValues, siderBroken } = searchFormStore;
const tableSorter = (a, b, colName) => (a[colName] - b[colName]);
const tableProps = { const tableProps = {
size: 'small', size: 'small',
bordered: true,
pagination: false,
columns: [ columns: [
{ title: '目的地', dataIndex: 'op', key: 'op' }, { title: '目的地', dataIndex: 'CityName', key: 'CityName' },
{ title: '总间夜', dataIndex: 'action', key: 'action' }, {
{ title: '主推', dataIndex: 'action', key: 'action' }, title: '总间夜',
{ title: '使用比例', dataIndex: 'action', key: 'action' }, dataIndex: 'TotalNum',
key: 'TotalNum',
sorter: (a, b) => tableSorter(a, b, 'TotalNum'),
render: (v, r) => (
<>
<Space direction={'vertical'}>
<Text strong>
{v}
{r.CPTotalNum && <Text type="secondary"> VS {r.CPTotalNum}</Text>}
</Text>
{r.CPTotalNum && <VSTag diffPercent={r.TotalNumPercent} />}
</Space>
</>
),
},
{
title: '主推',
dataIndex: 'RecomendNum',
key: 'RecomendNum',
sorter: (a, b) => tableSorter(a, b, 'RecomendNum'),
render: (v, r) => (
<>
<Space direction={'vertical'}>
<Text strong>
{v}
{r.CPRecomendNum && <Text type="secondary"> VS {r.CPRecomendNum}</Text>}
</Text>
{r.CPRecomendNum && <VSTag diffPercent={r.RecomendNumPercent} />}
</Space>
</>
),
},
{
title: '使用比例',
dataIndex: 'RecommendRate_100',
key: 'RecommendRate_100',
render: (v, r) => (
<>
<Space direction={'vertical'}>
<Text strong>
{v}
{r.RecommendRateDelta !== undefined && <Text type="secondary"> VS {r.CPRecommendRate_100}</Text>}
</Text>
{r.RecommendRateDelta !== undefined && <VSTag diffPercent={r.RecommendRateDelta} />}
</Space>
</>
),
},
], ],
}; };
@ -28,27 +82,30 @@ export default observer((props) => {
defaultValue={{ defaultValue={{
initialValue: { initialValue: {
...date_picker_store.formValues, ...date_picker_store.formValues,
...customerServicesStore.searchValues, ...HotelCruiseStore.searchValues,
}, },
// 'countryArea', 'DateType', 'dates', // 'countryArea', 'DateType', 'dates',
shows: ['DepartmentList', 'countryArea', 'orderStatus', 'bookType', 'recommandRate','hotelStar','DateType', 'dates',], shows: ['DepartmentList', 'countryArea', 'orderStatus', 'hotelBookType', 'hotelRecommandRate', 'hotelStar', 'DateType', 'dates'],
sort: { DateType: 101, dates: 102 }, sort: { DateType: 101, dates: 102 },
fieldProps: { fieldProps: {
DepartmentList: { show_all: true, mode: 'multiple' }, DepartmentList: { show_all: true, mode: 'multiple' },
countryArea: { show_all: true },
orderStatus: { show_all: true }, orderStatus: { show_all: true },
hotelBookType: { show_all: true },
hotelRecommandRate: { show_all: true },
// years: { hide_vs: false }, // years: { hide_vs: false },
DateType: { disabledKeys: ['applyDate'] }, DateType: { disabledKeys: ['applyDate'] },
}, },
}} }}
onSubmit={(_err, obj, form) => { onSubmit={(_err, obj, form) => {
customerServicesStore.setSearchValues(obj, form); HotelCruiseStore.setSearchValues(obj, form);
// customerServicesStore.fetchDestinationGroupCount(); HotelCruiseStore.getHotelData(obj);
}} }}
/> />
</Col> </Col>
</Row> </Row>
<section> <section>
<Table {...tableProps} bordered /> <Table {...tableProps} bordered {...{ loading, dataSource }} rowKey={(record) => record.CityName} />
</section> </section>
</> </>
); );

Loading…
Cancel
Save