From 8228e07209b011cd92f7a4e2e63cd35d11c3d00b Mon Sep 17 00:00:00 2001 From: Lei OT Date: Tue, 14 Nov 2023 10:35:28 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20=E9=A2=84=E8=AE=BE;=20=E5=AF=BC?= =?UTF-8?q?=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/libs/ht.js | 4 +- src/utils/commons.js | 14 +++++++ src/views/DataPivot.jsx | 83 +++++++++++++++++++++++++---------------- 3 files changed, 66 insertions(+), 35 deletions(-) diff --git a/src/libs/ht.js b/src/libs/ht.js index bcf85dc..b79c1c8 100644 --- a/src/libs/ht.js +++ b/src/libs/ht.js @@ -177,7 +177,7 @@ export const KPISubjects = [ * @returns */ export const pivotBy = (data, [rows, columns, date]) => { - // console.time('pivot----'); + console.time('pivot----'); console.log('pivotBy', [rows, columns, date]); const groupbyKeys = flush([].concat(rows, columns, [date])); const getKeys = (keys) => keys.map((keyField) => [...new Set(data.map((f) => f[keyField]))]); @@ -278,7 +278,7 @@ export const pivotBy = (data, [rows, columns, date]) => { const columnsData = groupBy(data, (row) => columns.map((kk) => `${row[kk]}`).join('=@=')); const summaryColumns = transposeData(columns, columnsData, ['rows', rows]); - // console.timeEnd('pivot----'); + console.timeEnd('pivot----'); return { data: pivotResult, columnValues: [rowsKeys, columnsKeys, dateKeys], summaryRows, summaryColumns }; }; diff --git a/src/utils/commons.js b/src/utils/commons.js index 0073b1c..a2b7c27 100644 --- a/src/utils/commons.js +++ b/src/utils/commons.js @@ -533,3 +533,17 @@ export const getNestedValue = (obj, keyArr) => { return acc && acc[curr]; }, obj); }; + +/** + * 计算笛卡尔积 + */ +export const cartesianProductArray = (arr, sep = '_', index = 0, prefix = '') => { + let result = []; + if(index === arr.length){ + return [prefix]; + } + arr[index].forEach(item => { + result = result.concat(cartesianProductArray(arr, sep, index+1, prefix ? `${prefix}${sep}${item}` : `${item}`)); + }); + return result; +}; diff --git a/src/views/DataPivot.jsx b/src/views/DataPivot.jsx index cba838c..dde0831 100644 --- a/src/views/DataPivot.jsx +++ b/src/views/DataPivot.jsx @@ -2,45 +2,37 @@ import { useContext, useEffect, useState } from 'react'; import { observer } from 'mobx-react'; import { useParams } from 'react-router-dom'; import { stores_Context } from '../config'; -import { Row, Col, Spin, Table, Select, Typography, Card, Button } from 'antd'; -import { cloneDeep, groupBy, isEmpty, omit, pick, sortBy, unique } from '../utils/commons'; +import { Row, Col, Spin, Table, Select, Typography, Card, Button, Space, Divider } from 'antd'; +import { cloneDeep, groupBy, isEmpty, omit, pick, sortBy, unique, cartesianProductArray } from '../utils/commons'; import { dataFieldAlias, pivotBy } from '../libs/ht'; import SearchForm from '../components/search/SearchForm'; import { Line } from '@ant-design/plots'; import DateGroupRadio from '../components/DateGroupRadio'; +import { TableExportBtn } from './../components/Data'; const { Text } = Typography; const filterFields = [ - { key: 'country', label: '国籍' }, { key: 'SourceType', label: '来源类型' }, { key: 'productType', label: '产品类型' }, + { key: 'country', label: '国籍' }, + { key: 'CLI_NO', label: '线路' }, + // { key: 'destination', label: '目的地' }, + { key: 'COLI_LineClass', label: '页面类型' }, { key: 'guestGroupType', label: '客群类别' }, { key: 'travelMotivation', label: '出行动机' }, - { key: 'operatorName', label: '顾问' }, - { key: 'WebCode', label: '来源站点' }, - // todo: 目的地, 目的地国家, 页面类型[PPC, NL...] + // { key: 'operatorName', label: '顾问' }, + // { key: 'WebCode', label: '来源站点' }, + // todo: 目的地, 目的地国家, 页面类型LineClass[PPC, NL...], 线路line, ]; const filterFieldsMapped = filterFields.reduce((r, v) => ({ ...r, [v.key]: v }), {}); const quickOptions = [ - { label: '国籍×产品', fields: [['country'], ['productType']] }, - { label: '产品×客群', fields: [['productType'], ['guestGroupType']] }, + // { label: '国籍×产品', fields: [['country'], ['productType']] }, + { label: '[ 产品×客群 ]×[ ]', fields: [['productType', 'guestGroupType'], []] }, + { label: '[ 国籍×客群 ]×[ ]', fields: [['country', 'guestGroupType'], []] }, + // { label: '[ 国籍×客群 ]×[ ]', fields: [['country', 'guestGroupType'], []] }, ]; -/** - * 计算笛卡尔积 - */ -const cartesianProductArray = (arr, sep = '_', index = 0, prefix = '') => { - let result = []; - if(index === arr.length){ - return [prefix]; - } - arr[index].forEach(item => { - result = result.concat(cartesianProductArray(arr, sep, index+1, prefix ? `${prefix}${sep}${item}` : `${item}`)); - }); - return result; -}; - // 注意TdCell要提到DataTable作用域外声明 const TdCell = (tdprops) => { // onMouseEnter, onMouseLeave在数据量多的时候,会严重阻塞表格单元格渲染,严重影响性能 @@ -151,21 +143,36 @@ export default observer((props) => { // 透视配置:行列选项 // const [leftFields, setLeftFields] = useState(filterFields); - const [rightFields, setRightFields] = useState(filterFields); + const [rightFields, setRightFields] = useState(filterFields); // select 的option const [rowFields, setRowFields] = useState([]); const [columnFields, setColumnFields] = useState([]); + // 预设的选项 const [rowSelection, setRowSelection] = useState(); const [columnSelection, setColumnSelection] = useState(); const quickOpt = (i) => { const { fields: pivotFields } = quickOptions[i]; const [row, col] = pivotFields; setRowSelection(Object.values(pick(filterFieldsMapped, row))); - setColumnSelection(filterFieldsMapped[col[0]]); + !isEmpty(col) ? setColumnSelection(filterFieldsMapped[col[0]]) : setColumnSelection([]); + setRowFields(row); + resetItemFilter(); + setPivotDateColumns(pivotFields); }; + const resetFields = () => { + // setRowFields([]); + // setColumnFields([]); + setRowSelection([]); + setColumnSelection([]); + resetItemFilter(); + + setPivotDateColumns([[], []]); + }; + const handleRowsPick = (v) => { + setRowSelection(v); const pickKeys = v.map((ele) => ele.key); setRowFields(pickKeys); // const leftFieldsMapped = leftFields.reduce((r, v) => ({ ...r, [v.key]: v }), {}); @@ -177,6 +184,7 @@ export default observer((props) => { }; const handleColsPick = (val) => { + setColumnSelection(val); const pickKeys = isEmpty(val) ? [] : Array.isArray(val) ? val.map((ele) => ele.key) : [val.key]; setColumnFields(pickKeys); const afterLeft = Object.values(omit(filterFieldsMapped, rowFields)); @@ -323,11 +331,19 @@ export default observer((props) => { ( - // - // ))} + extra={ + + 预设: + {quickOptions.map((ele, elei) => ( + + ))} + + + } > @@ -352,8 +368,7 @@ export default observer((props) => { style={{ width: '100%' }} placeholder={`选择`} onChange={(v) => handleRowsPick(v)} - // value={sale_store.salesTrade.pickSales} - // value={rowSelection} + value={rowSelection} maxTagCount={2} maxTagPlaceholder={(omittedValues) => ` + ${omittedValues.length} 更多...`} allowClear={true} @@ -413,8 +428,7 @@ export default observer((props) => { style={{ width: '100%' }} placeholder={`选择`} onChange={(v) => handleColsPick(v)} - // value={sale_store.salesTrade.pickSales} - // value={columnSelection} + value={columnSelection} maxTagCount={2} maxTagPlaceholder={(omittedValues) => ` + ${omittedValues.length} 更多...`} allowClear={true} @@ -494,6 +508,9 @@ export default observer((props) => {

透视汇总表: {dataFieldAlias[lineConfig.yField].label}

+ + +