diff --git a/src/stores/Distribution.js b/src/stores/Distribution.js index f21a92b..d394d9a 100644 --- a/src/stores/Distribution.js +++ b/src/stores/Distribution.js @@ -1,19 +1,19 @@ import { makeAutoObservable, runInAction, toJS } from 'mobx'; import * as req from '../utils/request'; -import { DATE_FORMAT } from './../config'; +import { DATE_FORMAT, SMALL_DATETIME_FORMAT } from './../config'; import moment from 'moment'; import { isEmpty, pick, sortBy, fixTo2Decimals, cloneDeep, unique } from '../utils/commons'; const modelMapper = { - 'tourDays': { url: '/service-Analyse2/GetTradeApartByTourDays', keySort: true }, - 'PML': { url: '/service-Analyse2/GetTradeApartByPML', keySort: true }, - 'ConfirmDays': { url: '/service-Analyse2/GetTradeApartByConfirmDays', keySort: true }, - 'ApplyDays': { url: '/service-Analyse2/GetTradeApartByApplyDays', keySort: true }, - 'PersonNum': { url: '/service-Analyse2/GetTradeApartByPersonNum', keySort: true }, - 'destination': { url: '/service-Analyse2/GetTradeApartByDestination', keySort: false }, - 'GlobalDestination': { url: '/service-Analyse2/GetTradeApartByGlobalDestination', keySort: false }, - 'destinationCountry': { url: '/service-Analyse2/GetTradeApartByDestinationCountry', keySort: false }, - 'guestCountry': { url: '/service-Analyse2/GetTradeApartByGuestCountry', keySort: false }, + 'tourDays': { url: '/service-Analyse2/GetTradeApartByTourDays', keySort: true, dynamicsX: false }, + 'PML': { url: '/service-Analyse2/GetTradeApartByPML', keySort: true, dynamicsX: false }, + 'ConfirmDays': { url: '/service-Analyse2/GetTradeApartByConfirmDays', keySort: true, dynamicsX: false }, + 'ApplyDays': { url: '/service-Analyse2/GetTradeApartByApplyDays', keySort: true, dynamicsX: false }, + 'PersonNum': { url: '/service-Analyse2/GetTradeApartByPersonNum', keySort: true, dynamicsX: false }, + 'destination': { url: '/service-Analyse2/GetTradeApartByDestination', keySort: false, dynamicsX: true, }, + 'GlobalDestination': { url: '/service-Analyse2/GetTradeApartByGlobalDestination', keySort: false, dynamicsX: true, }, + 'destinationCountry': { url: '/service-Analyse2/GetTradeApartByDestinationCountry', keySort: false, dynamicsX: true, }, + 'guestCountry': { url: '/service-Analyse2/GetTradeApartByGuestCountry', keySort: false, dynamicsX: true, }, }; class Distribution { constructor(appStore) { @@ -37,10 +37,11 @@ class Distribution { // 同比的参数: 去年同期 const [DateToY1, DateToY2] = [moment(param.Date1).subtract(1, 'year'), moment(param.Date2).subtract(1, 'year')]; param.DateToY1 = DateToY1.format(DATE_FORMAT); - param.DateToY2 = DateToY2.format(`${DATE_FORMAT} 23:59:59`); + param.DateToY2 = DateToY2.format(SMALL_DATETIME_FORMAT); param.DateToQ1 = DateToQ1.format(DATE_FORMAT); - param.DateToQ2 = DateToQ2.format(`${DATE_FORMAT} 23:59:59`); - const json = await req.fetchJSON(modelMapper[mkey].url, param); + param.DateToQ2 = DateToQ2.format(SMALL_DATETIME_FORMAT); + const dynamicsX = modelMapper[mkey].dynamicsX; + const json = dynamicsX === false ? await req.fetchJSON(modelMapper[mkey].url, param) : await this.getApartDataStep(param); if (json.errcode === 0) { const dataLength = json.result.length; const pickResult = dataLength > 20 ? json.result.slice(0, 30) : json.result; @@ -55,6 +56,20 @@ class Distribution { return this[mkey]; }; + getApartDataStep = async (param) => { + const mkey = this.curTab; + this[mkey] = { loading: true, dataSource: [] }; + const xParam = cloneDeep(param); + delete xParam.DateToY1; + delete xParam.DateToY2; + delete xParam.DateToQ1; + delete xParam.DateToQ2; + const { result, ...jsonY } = await req.fetchJSON(modelMapper[mkey].url, { ...xParam }); + const { result: resultToY } = await req.fetchJSON(modelMapper[mkey].url, { ...xParam, Date1: param.DateToY1, Date2: param.DateToY2 }); + const { result: resultToQ } = await req.fetchJSON(modelMapper[mkey].url, { ...xParam, Date1: param.DateToQ1, Date2: param.DateToQ2 }); + return { ...jsonY, result, resultToY, resultToQ }; + }; + /** * 明细 */ @@ -153,6 +168,17 @@ const calcDiff = ({ result, resultToY, resultToQ }, keySort) => { : 0, ConfirmOrderDiffY: resultMapped[row.key].ConfirmOrder - resultToYMapped[row.key].ConfirmOrder, ConfirmOrderDiffQ: resultMapped[row.key].ConfirmOrder - resultToQMapped[row.key].ConfirmOrder, + + SumOrderY: resultToYMapped?.[row.key]?.SumOrder || 0, + SumOrderToY: resultToYMapped?.[row.key]?.SumOrder + ? fixTo2Decimals(((resultMapped[row.key].SumOrder - resultToYMapped[row.key].SumOrder) / resultToYMapped[row.key].SumOrder) * 100) + : 0, + SumOrderQ: resultToQMapped?.[row.key]?.SumOrder || 0, + SumOrderToQ: resultToQMapped?.[row.key]?.SumOrder + ? fixTo2Decimals(((resultMapped[row.key].SumOrder - resultToQMapped[row.key].SumOrder) / resultToQMapped[row.key].SumOrder) * 100) + : 0, + SumOrderDiffY: resultMapped[row.key].SumOrder - resultToYMapped[row.key].SumOrder, + SumOrderDiffQ: resultMapped[row.key].SumOrder - resultToQMapped[row.key].SumOrder, }; return { ...resultMapped[row.key], ...diff, resultToY: resultToYMapped[row.key], resultToQ: resultToQMapped[row.key] }; }); diff --git a/src/utils/commons.js b/src/utils/commons.js index 76e2b77..d661781 100644 --- a/src/utils/commons.js +++ b/src/utils/commons.js @@ -541,9 +541,16 @@ export const numberFormatter = (number) => { return new Intl.NumberFormat().format(number); }; +/** + * @example + * const obj = { a: { b: 'c' } }; + * const keyArr = ['a', 'b']; + * getNestedValue(obj, keyArr); // Returns: 'c' + */ export const getNestedValue = (obj, keyArr) => { return keyArr.reduce((acc, curr) => { - return acc && acc[curr]; + return acc && acc.hasOwnProperty(curr) ? acc[curr] : undefined; + // return acc && acc[curr]; }, obj); }; diff --git a/src/views/Distribution.jsx b/src/views/Distribution.jsx index 84d7ec3..83d8cce 100644 --- a/src/views/Distribution.jsx +++ b/src/views/Distribution.jsx @@ -19,12 +19,19 @@ const apartOptions = [ { key: 'ConfirmDays', value: 'ConfirmDays', label: '成团周期' }, { key: 'ApplyDays', value: 'ApplyDays', label: '预定周期' }, { key: 'PersonNum', value: 'PersonNum', label: '人等' }, - { key: 'destination', value: 'destination', label: '国内目的地' }, - { key: 'GlobalDestination', value: 'GlobalDestination', label: '海外目的地' }, - { key: 'destinationCountry', value: 'destinationCountry', label: '目的地国籍' }, - { key: 'guestCountry', value: 'guestCountry', label: '客人国籍' }, + { key: 'destination', value: 'destination', label: '国内目的地', }, + { key: 'GlobalDestination', value: 'GlobalDestination', label: '海外目的地', }, + { key: 'destinationCountry', value: 'destinationCountry', label: '目的地国籍', }, + { key: 'guestCountry', value: 'guestCountry', label: '客人国籍', }, ]; +// 注意TdCell要提到DataTable作用域外声明 +const TdCell = (tdprops) => { + // onMouseEnter, onMouseLeave在数据量多的时候,会严重阻塞表格单元格渲染,严重影响性能 + const { onMouseEnter, onMouseLeave, ...restProps } = tdprops; + return ; +}; + export default observer(() => { const { date_picker_store: searchFormStore, DistributionStore } = useContext(stores_Context); const { formValues, formValuesToSub } = searchFormStore; @@ -74,6 +81,29 @@ export default observer(() => { }; const columns = [ { title: '#', dataIndex: 'label' }, + { + title: '预定', + dataIndex: 'SumOrder', + render: (v, r) => ( + <> + + + {v} + + + + + 同比: + + + 环比: + + + + + + ), + }, { title: '团数', dataIndex: 'ConfirmOrder', @@ -212,6 +242,7 @@ export default observer(() => {