perf: 销售进度: 导出列表; 小组多选

feature/pivot
Lei OT 2 years ago
parent 1aa6bfce18
commit 42f4cbd134

@ -2,7 +2,7 @@ import { useState, useEffect } from "react";
import { Tag, Button, message } from 'antd'; import { Tag, Button, message } from 'antd';
import { CaretUpOutlined, CaretDownOutlined, DownloadOutlined } from '@ant-design/icons'; import { CaretUpOutlined, CaretDownOutlined, DownloadOutlined } from '@ant-design/icons';
import { utils, writeFile } from "xlsx"; import { utils, writeFile } from "xlsx";
import { isEmpty } from "../utils/commons"; import { isEmpty, getNestedValue } from "../utils/commons";
/** /**
* @property diffPercent * @property diffPercent
@ -49,7 +49,7 @@ export const TableExportBtn = (props) => {
const data = props.dataSource.map((item) => { const data = props.dataSource.map((item) => {
const itemMapped = columnsMap.reduce((sv, kset) => { const itemMapped = columnsMap.reduce((sv, kset) => {
const render_val = typeof kset?.render === 'function' ? kset.render('', item) : null; const render_val = typeof kset?.render === 'function' ? kset.render('', item) : null;
const data_val = kset?.dataIndex ? item[kset.dataIndex] : undefined; const data_val = kset?.dataIndex ? (Array.isArray(kset.dataIndex) ? getNestedValue(item, kset.dataIndex) : item[kset.dataIndex]) : undefined;
const v = { [kset.title]: render_val || data_val }; const v = { [kset.title]: render_val || data_val };
return { ...sv, ...v }; return { ...sv, ...v };
}, {}); }, {});

@ -527,3 +527,9 @@ export function flush(collection) {
export const numberFormatter = (number) => { export const numberFormatter = (number) => {
return new Intl.NumberFormat().format(number); return new Intl.NumberFormat().format(number);
}; };
export const getNestedValue = (obj, keyArr) => {
return keyArr.reduce((acc, curr) => {
return acc && acc[curr];
}, obj);
};

@ -1,14 +1,16 @@
import React, { useContext } from 'react'; import React, { useContext } from 'react';
import { Row, Col, Table, Select, Space, Typography, Progress, Spin } from 'antd'; import { Row, Col, Table, Select, Space, Typography, Progress, Spin, Divider } from 'antd';
import { stores_Context } from '../config'; import { stores_Context } from '../config';
import { observer } from 'mobx-react'; import { observer } from 'mobx-react';
import * as comm from '../utils/commons'; import * as comm from '../utils/commons';
import SearchForm from './../components/search/SearchForm'; import SearchForm from './../components/search/SearchForm';
import { dataFieldAlias } from '../libs/ht'; import { dataFieldAlias, overviewGroup } from '../libs/ht';
import Donut from './../components/Donut'; import Donut from './../components/Donut';
import LineWithKPI from '../components/LineWithKPI'; import LineWithKPI from '../components/LineWithKPI';
import { TableExportBtn } from './../components/Data';
const { Text } = Typography; const { Text } = Typography;
const overviewGroupKeys = overviewGroup.map(item => item.key);
const Sale_KPI = () => { const Sale_KPI = () => {
const { sale_store, date_picker_store: searchFormStore } = useContext(stores_Context); const { sale_store, date_picker_store: searchFormStore } = useContext(stores_Context);
@ -16,10 +18,11 @@ const Sale_KPI = () => {
const { groupType, loading, operator, } = sale_store.salesTrade; const { groupType, loading, operator, } = sale_store.salesTrade;
const dataSource = [].concat(sale_store.salesTrade[groupType], operator); const dataSource = [].concat(sale_store.salesTrade[groupType], operator);
const yearData = Object.values(sale_store.salesTrade[groupType]?.[0]?.mData || {}); const yearData = sale_store.salesTrade[groupType].reduce((r, ele) => r.concat(Object.values(ele.mData)), []);
const operatorObjects = operator.map((v) => ({ key: v.groupsKey, value: v.groupsKey, label: v.groupsLabel })); const operatorObjects = operator.map((v) => ({ key: v.groupsKey, value: v.groupsKey, label: v.groupsLabel }));
const pageRefresh = async (queryData) => { const pageRefresh = async (queryData) => {
const overviewFlag = queryData.DepartmentList.toLowerCase() === 'all' || queryData.DepartmentList.toLowerCase().includes(','); const overviewFlag = queryData.DepartmentList.toLowerCase() === 'all'
|| overviewGroupKeys.includes(queryData.DepartmentList.toLowerCase()); // queryData.DepartmentList.toLowerCase().includes(',');
const _groupType = overviewFlag ? 'overview' : 'dept'; const _groupType = overviewFlag ? 'overview' : 'dept';
sale_store.setGroupType(_groupType); sale_store.setGroupType(_groupType);
sale_store.fetchOperatorTradeData(_groupType, { ...queryData, groupDateType: 'year' }); sale_store.fetchOperatorTradeData(_groupType, { ...queryData, groupDateType: 'year' });
@ -102,24 +105,72 @@ const Sale_KPI = () => {
}, },
...monthCol, ...monthCol,
]; ];
const columnsForExport = [
{
title: `#`,
dataIndex: 'groupsLabel',
editable: false,
width: '7.5em',
fixed: 'left',
},
{
title: '--',
dataIndex: 'rowLabel',
width: '10em',
fixed: 'left',
},
{
title: '年度',
dataIndex: 'yearML',
width: '10em',
fixed: 'left',
},
...new Array(12).fill(1).map((_, index) => {
return {
title: `${index + 1}`,
dataIndex: ['mData', `month_${String(index + 1).padStart(2, '0')}`], // , 'SumML'
valueType: 'digit',
width: '7.5em',
};
}),
];
const dataForExport = dataSource.reduce((r, ele) => {
const targetRow = {
groupsLabel: ele.groupsLabel,
rowLabel: '目标',
yearML: ele.yData.MLKPIvalue,
mData: Object.values(ele.mData).reduce((rt, et) => ({ ...rt, [`month_${et.dateVal}`]: et.MLKPIvalue }), {}),
};
const valRow = { groupsLabel: ele.groupsLabel, rowLabel: '完成', yearML: ele.yData.SumML, mData: Object.values(ele.mData).reduce((rt, et) => ({ ...rt, [`month_${et.dateVal}`]: et.SumML }), {}) };
const processRow = {
groupsLabel: ele.groupsLabel,
rowLabel: '进度(%)',
yearML: ele.yData.MLKPIrates,
mData: Object.values(ele.mData).reduce((rt, et) => ({ ...rt, [`month_${et.dateVal}`]: et.MLKPIrates }), {}),
};
r.push(targetRow, valRow, processRow);
return r;
}, []);
const lineConfig = { appendPadding: 10, xField: 'groupDateVal', yField: 'SumML', seriesField: 'groupsLabel', isGroup: true, smooth: true, meta: comm.cloneDeep(dataFieldAlias), }; const lineConfig = { appendPadding: 10, xField: 'groupDateVal', yField: 'SumML', seriesField: 'groupsLabel', isGroup: true, smooth: true, meta: comm.cloneDeep(dataFieldAlias), };
return ( return (
<div> <div>
<Row gutter={16} className='sticky-top' > <Row gutter={16} className="sticky-top">
<Col md={24} lg={24} xxl={24}> <Col md={24} lg={24} xxl={24}>
<SearchForm <SearchForm
defaultValue={{ defaultValue={{
initialValue: { initialValue: {
...formValues, ...formValues,
...sale_store.searchValues,
}, },
shows: ['DateType', 'DepartmentList', 'WebCode', 'IncludeTickets', 'years'], shows: ['DateType', 'DepartmentList', 'WebCode', 'IncludeTickets', 'years'],
fieldProps: { fieldProps: {
DepartmentList: { show_all: true }, DepartmentList: { show_all: false, mode: 'multiple', col: 5 },
WebCode: { show_all: true }, WebCode: { show_all: false, mode: 'multiple', col: 5 },
years: { hide_vs: true }, years: { hide_vs: true },
}, },
}} }}
onSubmit={(_err, obj, form, str) => { onSubmit={(_err, obj, form, str) => {
sale_store.setSearchValues(obj, form);
pageRefresh(obj); pageRefresh(obj);
}} }}
/> />
@ -167,6 +218,9 @@ const Sale_KPI = () => {
<Row> <Row>
<Col className="gutter-row" md={24}> <Col className="gutter-row" md={24}>
<Divider orientation="right">
<TableExportBtn label={'sales kpi'} {...{ columns: columnsForExport, dataSource: dataForExport }} />
</Divider>
<Table <Table
sticky sticky
key={`salesTradeTable`} key={`salesTradeTable`}

Loading…
Cancel
Save