diff --git a/src/components/BulletWithSort.jsx b/src/components/BulletWithSort.jsx index 13f9fe2..6622f1d 100644 --- a/src/components/BulletWithSort.jsx +++ b/src/components/BulletWithSort.jsx @@ -1,7 +1,7 @@ import { useEffect, useState } from 'react'; import { observer } from 'mobx-react'; import { Bullet } from '@ant-design/plots'; -import { sortBy, merge } from '../utils/commons'; +import { sortBy, merge, isEmpty } from '../utils/commons'; import { dataFieldAlias } from '../libs/ht'; export default observer((props) => { @@ -9,14 +9,22 @@ export default observer((props) => { // 处理进度图的数据格式, number -> array const dataParser = (origin) => { const { measureField, rangeField, targetField } = extProps; + const measureFieldArrKey = `${measureField}_arr`; const maxKPI = Math.max(...(origin || []).map((ele) => (ele?.[targetField] || 0))); const maxValue = Math.max(...(origin || []).map((ele) => ele[measureField])); const _max = Math.max(maxKPI, maxValue); const sortData = origin.sort(sortBy(measureField)).slice(-itemLength); // 顶格的值定在更远 - const _parseData = sortData?.map((ele) => ({ ...ele, [rangeField]: [0, Math.ceil(_max / 0.9)], [measureField]: [ele[measureField]], [targetField]: (ele?.[targetField] || 0) })); + const _parseData = sortData?.map((ele) => ({ ...ele, + [rangeField]: [0, Math.ceil(_max / 0.9)], + // [measureField]: [ele[measureField]], + [measureField]: ele[measureFieldArrKey] || [ele[measureField]], + [targetField]: (ele?.[targetField] || 0) + })); return _parseData; }; + const dataMapped = dataSource.reduce((r, v) => ({...r, [v.groupsLabel]: v}), {}); + const ifMergeTB = isEmpty(dataSource) ? false : !isEmpty(dataSource[0]?.[`${extProps.measureField}_arr`]); const [parseData, setParseData] = useState([]); useEffect(() => { @@ -35,11 +43,12 @@ export default observer((props) => { target: false, measure: { position: extProps?.layout === 'vertical' ? 'top' : 'right', - // style: { - // fill: '#063CAA', - // }, - formatter: (v) => { - return dataFieldAlias[extProps.measureField]?.formatter(v[extProps.measureField]) || v; + // formatter: (v, ...d) => { + // return dataFieldAlias[extProps.measureField]?.formatter(v[extProps.measureField]) || v; + // }, + content: (item, ...r) => { + const val = isEmpty(dataMapped) ? 0 : dataMapped[item.groupsLabel][extProps.measureField]; + return String(item?.mKey || '_0').endsWith('_0') ? '' : dataFieldAlias[extProps.measureField]?.formatter(val) || val; } }, }, @@ -57,8 +66,8 @@ export default observer((props) => { position: 'bottom', items: [ { - value: '实际', - name: '实际', + value: ifMergeTB ? '传统' : '实际', + name: ifMergeTB ? '传统' : '实际', marker: { symbol: 'square', style: { @@ -67,6 +76,17 @@ export default observer((props) => { }, }, }, + ...(ifMergeTB ? [{ + value: '商务', + name: '商务', + marker: { + symbol: 'square', + style: { + fill: '#61ddaa', + r: 5, + }, + }, + }] : []), { value: '目标', name: '目标', @@ -84,12 +104,28 @@ export default observer((props) => { tooltip: { customItems: (originalItems) => { // process originalItems, - const _items = originalItems.map((ele) => ({ - ...ele, - value: dataFieldAlias[ele.name]?.formatter(Number(ele.value)), - name: dataFieldAlias[ele.name]?.alias || ele.name, - })); - return _items; + const measureIndex = originalItems[0].name.split('_'); + const measureKey = measureIndex[0]; + const measureName = measureKey.endsWith('KPIvalue') ? '' : measureIndex[1] === 0 ? '传统' : '商务'; + const measureFieldArrKey = `${measureKey}_arr`; + const kpiKey = dataFieldAlias[measureKey]?.nestkey?.v; + const mItems = measureName + ? originalItems.reduce((r, ele) => { + const _itemMeasures = dataMapped[ele.title][measureFieldArrKey]; + r.push({ ...ele, color: '#5B8FF9', value: dataFieldAlias[measureKey]?.formatter(Number(_itemMeasures[0])), name: '传统' }); + r.push({ ...ele, color: '#61ddaa', value: dataFieldAlias[measureKey]?.formatter(Number(_itemMeasures[1])), name: '商务' }); + const _itemMeasureKPIv = dataMapped[ele.title][kpiKey]; + if (kpiKey && _itemMeasureKPIv) { + r.push({ ...ele, color: '#FF9845', value: dataFieldAlias[measureKey]?.formatter(Number(_itemMeasureKPIv)), name: dataFieldAlias[kpiKey].label }); + } + return r; + }, []) + : originalItems.map((ele) => ({ + ...ele, + value: dataFieldAlias[measureKey]?.formatter(Number(ele.value)), + name: dataFieldAlias[measureKey]?.alias || measureKey, + })); + return mItems; }, }, }, extProps); diff --git a/src/libs/ht.js b/src/libs/ht.js index eb5905b..6e327fb 100644 --- a/src/libs/ht.js +++ b/src/libs/ht.js @@ -112,7 +112,7 @@ export const dataFieldAlias = dataFieldOptions.reduce( (a, c) => ({ ...a, [c.value]: { ...c, alias: c.label, formatter: (v) => c.formatter(v) }, - [c.nestkey.v]: { ...c, value: c.nestkey.v, alias: `${c.label}目标`, label: `${c.label}目标`, formatter: (v) => c.formatter(v) }, + [c.nestkey.v]: { ...c, value: c.nestkey.v, alias: `${c.label}目标`, label: `${c.label}目标`, formatter: (v) => c.formatter(v), nestkey: { o: c.value } }, }), {} ); diff --git a/src/stores/Trade.js b/src/stores/Trade.js index 037b5d3..2aca077 100644 --- a/src/stores/Trade.js +++ b/src/stores/Trade.js @@ -1,6 +1,6 @@ import { makeAutoObservable, runInAction, toJS } from 'mobx'; import * as req from '../utils/request'; -import { isEmpty, sortBy, pick, merge, fixTo2Decimals, groupBy, sortKeys, fixToInt } from '../utils/commons'; +import { isEmpty, sortBy, pick, merge, fixTo2Decimals, groupBy, sortKeys, fixToInt, cloneDeep } from '../utils/commons'; import { dataFieldAlias } from './../libs/ht'; class Trade { @@ -16,7 +16,7 @@ class Trade { this.summaryData.loading = true; queryData.groupType = queryData?.groupType || 'overview'; queryData.groupDateType = 'year'; - const multiData = await this.fetchTradeDataAll(queryData); + const multiData = await this.fetchTradeDataAll(cloneDeep(queryData)); const { summary, traditional, biz } = multiData.result1; // console.log(JSON.stringify(summary), 'mmmmmmmmmmm'); const summaryData = { @@ -86,7 +86,7 @@ class Trade { queryData = Object.assign({}, this.searchPayloadHome, queryData); // queryData || this.searchPayloadHome; queryData.groupType = queryData?.groupType || 'overview'; Object.assign(queryData, { groupDateType: this.timeLineKey }); - const multiData = await this.fetchTradeDataAll(queryData); + const multiData = await this.fetchTradeDataAll(cloneDeep(queryData)); const { traditional, biz } = multiData.result1; // console.log(biz, 'mmmmmmmm', queryData, multiData); const mergeData = [].concat(traditional, biz); @@ -170,17 +170,19 @@ class Trade { /** * TOP */ - fetchTradeDataByType(orderType, queryData) { + async fetchTradeDataByType(orderType, queryData) { this.topData[orderType] = { loading: true, dataSource: [], originData: [] }; Object.assign(queryData, { groupType: orderType, groupDateType: 'year' }); - this.fetchTradeData(queryData).then((json) => { - if (json.errcode === 0) { - runInAction(() => { - this.topData[orderType].loading = false; - this.topData[orderType].dataSource = json.result1; - this.getTargetsRes(orderType); - }); - } + + const multiData = await this.fetchTradeDataAll(cloneDeep(queryData)); + const { traditional, biz, summary } = multiData.result1; + // console.log(biz, orderType, 'mmmmmmmm', queryData, multiData); + // const mergeData = [].concat(traditional, biz); + // const dateKeyData = groupBy(mergeData, ele => ele.groupDateVal); + runInAction(() => { + this.topData[orderType].loading = false; + this.topData[orderType].dataSource = summary; + this.getTargetsRes(orderType); }); } @@ -225,6 +227,7 @@ class Trade { return r; }, {}); const ByDate = sortKeys(groupBy(mergeRes, ele => ele.groupDateVal)); + // 按日期汇总 const summaryRows = Object.keys(ByDate).map(dateVal => { const sumFields = ['ConfirmOrder', 'SumOrder', 'SumML', 'transactions', 'SumPersonNum'].reduce( (r, skey) => ({ ...r, [skey]: ByDate[dateVal].reduce((a, c) => a + c[skey], 0) }), @@ -236,21 +239,29 @@ class Trade { ConfirmRates: row.SumOrder ? fixTo2Decimals((row.ConfirmOrder/row.SumOrder)*100) : 0, MLKPIrates: row.MLKPIvalue ? fixTo2Decimals((row.SumML/row.MLKPIvalue)*100) : 0, OrderValue: row.SumOrder ? fixToInt((row.SumML/row.SumOrder)) : 0, - groupsLabel: `总 `, // ${row.groupsLabel} + // groupsLabel: `总 `, // ${row.groupsLabel} ConfirmOrderKPIrates: row.ConfirmOrderKPIvalue ? fixTo2Decimals((row.ConfirmOrder/row.ConfirmOrderKPIvalue)*100) : 0, OrderKPIrates: row.OrderKPIvalue ? fixTo2Decimals((row.SumOrder/row.OrderKPIvalue)*100) : 0, // ConfirmRatesKPIrates: 0, // todo: })); - const summary = Object.keys(groupsData).map(groupsKey => { + // 按对象汇总 + const TMapped = traditional[resKey].reduce((r, v) => ({...r, [v.groupsKey]: v}), {}); + const BMapped = biz[resKey].reduce((r, v) => ({...r, [v.groupsKey]: v}), {}); + const summary = Object.keys(groupsData).map(groupsLabel => { + const _groupsKey = groupsData[groupsLabel]?.[0]?.groupsKey || ''; return ['ConfirmOrder', 'SumOrder', 'SumML', 'transactions', 'SumPersonNum'].reduce( - (r, skey) => ({ ...r, [skey]: groupsData[groupsKey].reduce((a, c) => a + c[skey], 0) }), - groupsData[groupsKey]?.[0] || {} + (r, skey) => ({ ...r, + [skey]: groupsData[groupsLabel].reduce((a, c) => a + c[skey], 0), + // [`${skey}_arr`]: groupsData[groupsLabel].map(sv => sv[skey]), + [`${skey}_arr`]: [ _groupsKey ? TMapped?.[_groupsKey]?.[skey] || 0 : 0, _groupsKey ? BMapped?.[_groupsKey]?.[skey] || 0 : 0,], + }), + groupsData[groupsLabel]?.[0] || {} ); }).map(row => ({...row, ConfirmRates: row.SumOrder ? fixTo2Decimals((row.ConfirmOrder/row.SumOrder)*100) : 0, MLKPIrates: row.MLKPIvalue ? fixTo2Decimals((row.SumML/row.MLKPIvalue)*100) : 0, OrderValue: row.SumOrder ? fixToInt((row.SumML/row.SumOrder)) : 0, - groupsLabel: `总 `, // ${row.groupsLabel} + // groupsLabel: `总 `, // ${row.groupsLabel} })); return Object.assign(res, { [resKey]: Object.assign({}, mergeItem, { summary, summaryRows }) }); }, {}); @@ -313,6 +324,7 @@ class Trade { {key: 'ConfirmOrder', title: '成行数', dataIndex: 'ConfirmOrder'}, {key: 'ConfirmRates', title: '成行率', dataIndex: 'ConfirmRates'}, {key: 'SumML', title: '毛利', dataIndex: 'SumML', render: (v) => dataFieldAlias.SumML.formatter(v)}, + {key: 'transactions', title: '营收', dataIndex: 'transactions', render: (v) => dataFieldAlias.transactions.formatter(v)}, ], dataSource: [] }; } diff --git a/src/views/Home.jsx b/src/views/Home.jsx index 39f45c4..ef5512c 100644 --- a/src/views/Home.jsx +++ b/src/views/Home.jsx @@ -54,7 +54,7 @@ export default observer(() => { TradeStore.resetData(); TradeStore.fetchSummaryData(Object.assign({}, queryData, { groupType })); TradeStore.fetchTradeDataByDate(queryData); - // TradeStore.fetchTradeDataByBU(queryData); + // // TradeStore.fetchTradeDataByBU(queryData); TradeStore.fetchTradeDataByMonth(queryData); const topSeriesF = _overviewFlag ? topSeries : topSeries.filter((ele) => ele.key !== 'dept'); setTopSeriesSet(topSeriesF); @@ -243,7 +243,7 @@ export default observer(() => {

- 英语区目标客户 (仅传统订单) + 英语区目标客户