yi-bi-ez-table 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.idea/ez-table.iml +12 -0
- package/.idea/modules.xml +8 -0
- package/angular/formatNumber.js +39 -0
- package/angular/formatPercent.js +4 -0
- package/calc-measure/calc-measure-hander.js +239 -0
- package/calc-measure/utils.js +384 -0
- package/constants.js +62 -0
- package/ez-agg-cunc-hander.js +186 -0
- package/ez-custom-agg-func/ez-custom-agg-func-hander.js +71 -0
- package/ez-custom-agg-func/utils.js +61 -0
- package/ezNumber.js +82 -0
- package/func.js +70 -0
- package/index.js +3 -0
- package/interface.js +2 -0
- package/package.json +16 -0
- package/prisma/seed.js +70 -0
- package/setBindDim.js +178 -0
- package/setDisplayData.js +207 -0
- package/setMergeData.js +198 -0
- package/table-core.js +620 -0
- package/table-header.js +1680 -0
- package/table-headerKeys.js +785 -0
- package/utils.js +910 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<module type="WEB_MODULE" version="4">
|
|
3
|
+
<component name="NewModuleRootManager">
|
|
4
|
+
<content url="file://$MODULE_DIR$">
|
|
5
|
+
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
|
|
6
|
+
<excludeFolder url="file://$MODULE_DIR$/temp" />
|
|
7
|
+
<excludeFolder url="file://$MODULE_DIR$/tmp" />
|
|
8
|
+
</content>
|
|
9
|
+
<orderEntry type="inheritedJdk" />
|
|
10
|
+
<orderEntry type="sourceFolder" forTests="false" />
|
|
11
|
+
</component>
|
|
12
|
+
</module>
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export function formatNumber(num, locale, digitsInfo) {
|
|
2
|
+
// const parts = digitsInfo.split('.')[1].split('-');
|
|
3
|
+
// const minFractionDigits = parseInt(parts[0]);
|
|
4
|
+
// const maxFractionDigits = parseInt(parts[1]);
|
|
5
|
+
// const format = {
|
|
6
|
+
// style: 'decimal',
|
|
7
|
+
// minimumFractionDigits: minFractionDigits,
|
|
8
|
+
// maximumFractionDigits: maxFractionDigits,
|
|
9
|
+
// };
|
|
10
|
+
// return new Intl.NumberFormat(locale, format).format(num);
|
|
11
|
+
// return angularFormatNumber(num, locale, digitsInfo);
|
|
12
|
+
const parts = digitsInfo.split('.')[1].split('-');
|
|
13
|
+
const minDigits = parseInt(parts[0]);
|
|
14
|
+
const maxDigits = parseInt(parts[1]);
|
|
15
|
+
// 四舍五入到最大小数位
|
|
16
|
+
num = roundNumber(num, maxDigits);
|
|
17
|
+
const [integerPart, decimalPart] = num.toString().split('.');
|
|
18
|
+
// 千分位
|
|
19
|
+
const formattedInteger = integerPart.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
20
|
+
// 补充最小小数位
|
|
21
|
+
let formattedDecimal = decimalPart ? decimalPart : '';
|
|
22
|
+
while (formattedDecimal.length < minDigits) {
|
|
23
|
+
formattedDecimal += '0';
|
|
24
|
+
}
|
|
25
|
+
return decimalPart || minDigits > 0 ? `${formattedInteger}.${formattedDecimal}` : formattedInteger;
|
|
26
|
+
}
|
|
27
|
+
function roundNumber(num, scale) {
|
|
28
|
+
if (!("" + num).includes("e")) {
|
|
29
|
+
return +(Math.round((num + "e+" + scale)) + "e-" + scale);
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
const arr = ("" + num).split("e");
|
|
33
|
+
let sig = "";
|
|
34
|
+
if (+arr[1] + scale > 0) {
|
|
35
|
+
sig = "+";
|
|
36
|
+
}
|
|
37
|
+
return +(Math.round((+arr[0] + "e" + sig + (+arr[1] + scale))) + "e-" + scale);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import { calcAgg } from "../ez-agg-cunc-hander";
|
|
2
|
+
import { calcDateRangeSum, calculateAccumulation, getDateDate, getGroupSumExtra, getSumExtra, handleCalc, recursionForLastButTwo, setCustomRank, setGroupCalc, setGroupCustomRank, setGroupRank, setRank, } from "./utils";
|
|
3
|
+
// export type TMeasureType = 'NORMAL' | 'SUM' | 'DIFFERENCE' | 'DIVISION' | 'RATE' | 'RATIO' | 'CUSTOM' | 'CONDITION' | 'DATE_RANGE_SUM' | 'CORRELATION' | 'GLOBAL_ACC' | 'GROUP_ACC' | 'MAX' | 'GROUP_MAX' | 'MIN' | 'GROUP_MIN' | 'AVG' | 'AVG_NON_ZERO' | 'GROUP_AVG' | 'GROUP_AVG_NON_ZERO' | 'CUSTOM_RANK' | 'GROUP_RATIO';export type TAggFunc = 'SUM' | 'MEDIAN' | 'AVG' | 'AVG_NON_ZERO' | 'MAX' | 'MIN' | 'COUNT' | 'DISTINC COUNT' | 'DISTINC_COUNT' | 'CUSTOM';
|
|
4
|
+
// 计算度量
|
|
5
|
+
const EZCalcMeasureHander = {
|
|
6
|
+
// 求和
|
|
7
|
+
'SUM': (params) => {
|
|
8
|
+
return handleCalc(params.header.computeFn, { data: params.data.data }, params.headerKeysDic);
|
|
9
|
+
},
|
|
10
|
+
// 差值
|
|
11
|
+
'DIFFERENCE': (params) => {
|
|
12
|
+
const newData = getDateDate(params);
|
|
13
|
+
return handleCalc(params.header.computeFn, { data: newData }, params.headerKeysDic);
|
|
14
|
+
},
|
|
15
|
+
// 比值
|
|
16
|
+
'DIVISION': (params) => {
|
|
17
|
+
return handleCalc(params.header.computeFn, { data: params.data.data }, params.headerKeysDic);
|
|
18
|
+
},
|
|
19
|
+
// 增长率
|
|
20
|
+
'RATE': (params) => {
|
|
21
|
+
return handleCalc(params.header.computeFn, { data: params.data.data }, params.headerKeysDic);
|
|
22
|
+
},
|
|
23
|
+
// 占比
|
|
24
|
+
'RATIO': (params) => {
|
|
25
|
+
const { header, data, headerKeysDic } = params;
|
|
26
|
+
const extra = {
|
|
27
|
+
sum: {},
|
|
28
|
+
};
|
|
29
|
+
if (header.sumKeyList?.length) {
|
|
30
|
+
extra.sum = {
|
|
31
|
+
...extra.sum,
|
|
32
|
+
...getSumExtra(header, data),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
return handleCalc(header.computeFn, { data: data.data, extra }, headerKeysDic);
|
|
36
|
+
},
|
|
37
|
+
// 分组占比
|
|
38
|
+
'GROUP_RATIO': (params) => {
|
|
39
|
+
const { header, data, headerKeysDic } = params;
|
|
40
|
+
const extra = {
|
|
41
|
+
sum: {},
|
|
42
|
+
};
|
|
43
|
+
if (header.groupSumKeyList?.length) {
|
|
44
|
+
extra.sum = {
|
|
45
|
+
...extra.sum,
|
|
46
|
+
...getGroupSumExtra(header, data),
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
return handleCalc(header.computeFn, { data: data.data, extra }, headerKeysDic);
|
|
50
|
+
},
|
|
51
|
+
// 日期区间求和
|
|
52
|
+
'DATE_RANGE_SUM': (params) => {
|
|
53
|
+
const { header, data } = params;
|
|
54
|
+
return calcDateRangeSum(header, data.data);
|
|
55
|
+
},
|
|
56
|
+
// 全局累加
|
|
57
|
+
'GLOBAL_ACC': (params) => {
|
|
58
|
+
const { header, dataList, firstDim, headerKeysDic } = params;
|
|
59
|
+
const sortList = header.computeParam?.sortListOfAcc?.length ?
|
|
60
|
+
header.computeParam.sortListOfAcc :
|
|
61
|
+
[{
|
|
62
|
+
displayNameList: ['维度', firstDim.key],
|
|
63
|
+
value: 'ascend'
|
|
64
|
+
}];
|
|
65
|
+
const field = header.calcKeyList[0];
|
|
66
|
+
calculateAccumulation(dataList, header.key, field, sortList, headerKeysDic);
|
|
67
|
+
},
|
|
68
|
+
// 分组累加
|
|
69
|
+
'GROUP_ACC': (params) => {
|
|
70
|
+
const { header, tree, firstDim, headerKeysDic } = params;
|
|
71
|
+
const sortList = header.computeParam?.sortListOfAcc?.length ?
|
|
72
|
+
header.computeParam.sortListOfAcc :
|
|
73
|
+
[{
|
|
74
|
+
displayNameList: ['维度', firstDim.key],
|
|
75
|
+
value: 'ascend'
|
|
76
|
+
}];
|
|
77
|
+
const field = header.calcKeyList[0];
|
|
78
|
+
// calcGroupAcc(tree, header, field, sortList, headerKeysDic);
|
|
79
|
+
recursionForLastButTwo(tree, data => {
|
|
80
|
+
calculateAccumulation(data.children, header.key, field, sortList, headerKeysDic);
|
|
81
|
+
});
|
|
82
|
+
},
|
|
83
|
+
// 最大值
|
|
84
|
+
'MAX': (params) => {
|
|
85
|
+
const { header, dataList, data, tree } = params;
|
|
86
|
+
const headerKey = header.key;
|
|
87
|
+
const field = header.calcKeyList[0];
|
|
88
|
+
const max = calcAgg({
|
|
89
|
+
aggKey: 'MAX',
|
|
90
|
+
calcKey: field,
|
|
91
|
+
dataList: dataList,
|
|
92
|
+
});
|
|
93
|
+
dataList.forEach(item => {
|
|
94
|
+
item.data[headerKey] = max;
|
|
95
|
+
});
|
|
96
|
+
},
|
|
97
|
+
// 最小值
|
|
98
|
+
'MIN': (params) => {
|
|
99
|
+
const { header, dataList } = params;
|
|
100
|
+
const headerKey = header.key;
|
|
101
|
+
const field = header.calcKeyList[0];
|
|
102
|
+
const min = calcAgg({
|
|
103
|
+
aggKey: 'MIN',
|
|
104
|
+
calcKey: field,
|
|
105
|
+
dataList: dataList,
|
|
106
|
+
});
|
|
107
|
+
dataList.forEach(item => {
|
|
108
|
+
item.data[headerKey] = min;
|
|
109
|
+
});
|
|
110
|
+
},
|
|
111
|
+
// 分组最大值
|
|
112
|
+
'GROUP_MAX': (params) => {
|
|
113
|
+
const { header, tree } = params;
|
|
114
|
+
const field = header.calcKeyList[0];
|
|
115
|
+
setGroupCalc('MAX', header.key, field, tree);
|
|
116
|
+
},
|
|
117
|
+
// 分组最小值
|
|
118
|
+
'GROUP_MIN': (params) => {
|
|
119
|
+
const { header, tree } = params;
|
|
120
|
+
const field = header.calcKeyList[0];
|
|
121
|
+
setGroupCalc('MIN', header.key, field, tree);
|
|
122
|
+
},
|
|
123
|
+
// 平均值
|
|
124
|
+
'AVG': (params) => {
|
|
125
|
+
const { header, dataList } = params;
|
|
126
|
+
const headerKey = header.key;
|
|
127
|
+
const field = header.calcKeyList[0];
|
|
128
|
+
const value = calcAgg({
|
|
129
|
+
aggKey: 'AVG',
|
|
130
|
+
calcKey: field,
|
|
131
|
+
dataList: dataList,
|
|
132
|
+
});
|
|
133
|
+
dataList.forEach(item => {
|
|
134
|
+
item.data[headerKey] = value;
|
|
135
|
+
});
|
|
136
|
+
},
|
|
137
|
+
// 平均值非零
|
|
138
|
+
'AVG_NON_ZERO': (params) => {
|
|
139
|
+
const { header, dataList } = params;
|
|
140
|
+
const calcKey = header.key;
|
|
141
|
+
const field = header.calcKeyList[0];
|
|
142
|
+
const value = calcAgg({
|
|
143
|
+
aggKey: 'AVG_NON_ZERO',
|
|
144
|
+
calcKey: field,
|
|
145
|
+
dataList: dataList,
|
|
146
|
+
});
|
|
147
|
+
dataList.forEach(item => {
|
|
148
|
+
item.data[calcKey] = value;
|
|
149
|
+
});
|
|
150
|
+
},
|
|
151
|
+
// 分组平均值
|
|
152
|
+
'GROUP_AVG': (params) => {
|
|
153
|
+
const { header, tree } = params;
|
|
154
|
+
const field = header.calcKeyList[0];
|
|
155
|
+
setGroupCalc('AVG', header.key, field, tree);
|
|
156
|
+
},
|
|
157
|
+
// 分组平均值(非零)
|
|
158
|
+
'GROUP_AVG_NON_ZERO': (params) => {
|
|
159
|
+
const { header, tree } = params;
|
|
160
|
+
const field = header.calcKeyList[0];
|
|
161
|
+
setGroupCalc('AVG_NON_ZERO', header.key, field, tree);
|
|
162
|
+
},
|
|
163
|
+
// 全局降序排名
|
|
164
|
+
'GLOBAL_RANK_DESC': (params) => {
|
|
165
|
+
const { header, dataList } = params;
|
|
166
|
+
const headerKey = header.key;
|
|
167
|
+
const field = header.calcKeyList[0];
|
|
168
|
+
setRank('descend', dataList, headerKey, field, header.computeParam?.measureList);
|
|
169
|
+
},
|
|
170
|
+
// 全局升序排名
|
|
171
|
+
'GLOBAL_RANK_ASC': (params) => {
|
|
172
|
+
const { header, dataList } = params;
|
|
173
|
+
const headerKey = header.key;
|
|
174
|
+
const field = header.calcKeyList[0];
|
|
175
|
+
setRank('ascend', dataList, headerKey, field, header.computeParam?.measureList);
|
|
176
|
+
},
|
|
177
|
+
// 分组升序排名
|
|
178
|
+
'GROUP_RANK_ASC': (params) => {
|
|
179
|
+
const { header, tree } = params;
|
|
180
|
+
const headerKey = header.key;
|
|
181
|
+
const field = header.calcKeyList[0];
|
|
182
|
+
setGroupRank('ascend', headerKey, field, tree, header.computeParam?.measureList);
|
|
183
|
+
},
|
|
184
|
+
// 分组降序排名
|
|
185
|
+
'GROUP_RANK_DESC': (params) => {
|
|
186
|
+
const { header, tree } = params;
|
|
187
|
+
const headerKey = header.key;
|
|
188
|
+
const field = header.calcKeyList[0];
|
|
189
|
+
setGroupRank('descend', headerKey, field, tree, header.computeParam?.measureList);
|
|
190
|
+
},
|
|
191
|
+
// 自定义排名
|
|
192
|
+
'CUSTOM_RANK': (params) => {
|
|
193
|
+
const { header, dataList, tree } = params;
|
|
194
|
+
const { rankTarget, rankOrder, rankWay } = header.computeParam;
|
|
195
|
+
const headerKey = header.key;
|
|
196
|
+
const field = header.calcKeyList[0];
|
|
197
|
+
switch (rankTarget) {
|
|
198
|
+
case 'GLOBAL':
|
|
199
|
+
setCustomRank(rankOrder, rankWay, dataList, headerKey, field, header.computeParam?.measureList, header.computeParam?.rankDimList);
|
|
200
|
+
break;
|
|
201
|
+
case 'GROUP':
|
|
202
|
+
setGroupCustomRank(rankOrder, rankWay, tree, headerKey, field, header.computeParam?.measureList, header.computeParam?.rankDimList);
|
|
203
|
+
break;
|
|
204
|
+
default:
|
|
205
|
+
break;
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
'CUSTOM': (params) => {
|
|
209
|
+
const { header, data, headerKeysDic } = params;
|
|
210
|
+
const extra = {
|
|
211
|
+
sum: {},
|
|
212
|
+
header,
|
|
213
|
+
};
|
|
214
|
+
if (header.sumKeyList?.length) {
|
|
215
|
+
extra.sum = {
|
|
216
|
+
...extra.sum,
|
|
217
|
+
...getSumExtra(header, data),
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
if (header.groupSumKeyList?.length) {
|
|
221
|
+
extra.sum = {
|
|
222
|
+
...extra.sum,
|
|
223
|
+
...getGroupSumExtra(header, data),
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
const newData = getDateDate(params);
|
|
227
|
+
const value = handleCalc(header.computeFn, { data: newData, extra }, headerKeysDic);
|
|
228
|
+
return value;
|
|
229
|
+
},
|
|
230
|
+
'CONDITION': (params) => {
|
|
231
|
+
return EZCalcMeasureHander['CUSTOM'](params);
|
|
232
|
+
},
|
|
233
|
+
};
|
|
234
|
+
export function getCalcRowValue(params) {
|
|
235
|
+
if (EZCalcMeasureHander[params.header.measureType || params.header.dimType]) {
|
|
236
|
+
return EZCalcMeasureHander[params.header.measureType || params.header.dimType](params);
|
|
237
|
+
}
|
|
238
|
+
return undefined;
|
|
239
|
+
}
|
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
import { format, addDays, differenceInDays } from "date-fns";
|
|
2
|
+
import { calcAgg } from "../ez-agg-cunc-hander";
|
|
3
|
+
import { convertToTree, getCalcValue, getDateList, setSortDataList } from "../utils";
|
|
4
|
+
export function handleCalc(computeFn, data, headerKeysDic) {
|
|
5
|
+
//(window as any).getSize = measure => getSize(measure, data, headerKeysDic);
|
|
6
|
+
return getCalcValue(computeFn, data);
|
|
7
|
+
}
|
|
8
|
+
export function getTopData(item) {
|
|
9
|
+
let top = item;
|
|
10
|
+
const findTop = (data) => {
|
|
11
|
+
if (data?.parent) {
|
|
12
|
+
top = data.parent;
|
|
13
|
+
findTop(data.parent);
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
findTop(item);
|
|
17
|
+
return top;
|
|
18
|
+
}
|
|
19
|
+
export function calcDateRangeSum(header, initData) {
|
|
20
|
+
const headerDate = header.label;
|
|
21
|
+
const firstDate = format(addDays(new Date(headerDate), 1), 'yyyy-MM-dd');
|
|
22
|
+
const first = header.dateRangeSumList[0];
|
|
23
|
+
const second = header.dateRangeSumList[1];
|
|
24
|
+
const firstIndex = first.dateList.findIndex(d => d === headerDate);
|
|
25
|
+
const prefixI = first.key.indexOf(']');
|
|
26
|
+
const firstIndexOfKey = prefixI > -1 ? `${first.key.substring(0, prefixI)}[${first.dateList[firstIndex]}]${first.key.substring(prefixI)}` : `${first.key}[${first.dateList[firstIndex]}]`;
|
|
27
|
+
let lastIndex = firstIndex;
|
|
28
|
+
for (let i = firstIndex + 1, leng = first.dateList.length; i < leng; i++) {
|
|
29
|
+
const date = first.dateList[i];
|
|
30
|
+
const dateFirstKey = prefixI > -1 ? `${first.key.substring(0, prefixI)}[${date}]${first.key.substring(prefixI)}` : `${first.key}[${date}]`;
|
|
31
|
+
if (initData.data[dateFirstKey] || initData.data[dateFirstKey] === 0) {
|
|
32
|
+
lastIndex = i - 1;
|
|
33
|
+
break;
|
|
34
|
+
}
|
|
35
|
+
if (i === first.dateList.length - 1) {
|
|
36
|
+
// 标志结尾
|
|
37
|
+
lastIndex = -2;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
let total = null;
|
|
41
|
+
if (initData.data[firstIndexOfKey] || initData.data[firstIndexOfKey] === 0) {
|
|
42
|
+
const dateList = getDateList(new Date(addDays(new Date(headerDate), 1)), lastIndex !== -2 ?
|
|
43
|
+
new Date(addDays(new Date(headerDate), lastIndex - firstIndex + 1)) :
|
|
44
|
+
new Date(second.dateList[second.dateList.length - 1]));
|
|
45
|
+
total = 0;
|
|
46
|
+
const secondPrefixI = second.key.indexOf(']');
|
|
47
|
+
dateList.forEach(d => {
|
|
48
|
+
const dateSecondKey = secondPrefixI > -1 ? `${second.key.substring(0, secondPrefixI)}[${d}]${second.key.substring(secondPrefixI)}` : `${second.key}[${d}]`;
|
|
49
|
+
total += (initData.data[dateSecondKey] || 0);
|
|
50
|
+
});
|
|
51
|
+
initData.data[header.key] = total;
|
|
52
|
+
}
|
|
53
|
+
return total;
|
|
54
|
+
}
|
|
55
|
+
const sumData = ({ sum = {}, children = [] }, key, accessor = d => d.sum[key] || 0) => {
|
|
56
|
+
return sum[key] = children.reduce((total, child) => total + accessor(child), 0);
|
|
57
|
+
};
|
|
58
|
+
const sumParent = (data, normalMeasureKeyList) => {
|
|
59
|
+
if (!data.parent.sum) {
|
|
60
|
+
data.parent.sum = {};
|
|
61
|
+
}
|
|
62
|
+
for (const header of normalMeasureKeyList) {
|
|
63
|
+
sumData(data.parent, header.key);
|
|
64
|
+
}
|
|
65
|
+
if (data.parent.parent && data.parent.parent.children[data.parent.parent.children - 1] === data.parent) {
|
|
66
|
+
sumParent(data.parent, normalMeasureKeyList);
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
export function calculateAccumulation(dataList, accKey, measureKey, sortList, headerKeysDic, inData = true) {
|
|
70
|
+
sortList = [...sortList].reverse();
|
|
71
|
+
const newDataList = setSortDataList(dataList, sortList, headerKeysDic);
|
|
72
|
+
let previousAccumulation = 0;
|
|
73
|
+
for (let leaf of newDataList) {
|
|
74
|
+
if (inData) {
|
|
75
|
+
leaf.data[accKey] = (leaf.data[measureKey] || 0) + previousAccumulation;
|
|
76
|
+
previousAccumulation = leaf.data[accKey] || 0;
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
leaf[accKey] = (leaf[measureKey] || 0) + previousAccumulation;
|
|
80
|
+
previousAccumulation = leaf[accKey] || 0;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
export function setGroupCalc(type, headerKey, calcKey, tree) {
|
|
85
|
+
recursionForLastButTwo(tree, data => {
|
|
86
|
+
const value = calcAgg({
|
|
87
|
+
aggKey: type,
|
|
88
|
+
calcKey,
|
|
89
|
+
dataList: data.children,
|
|
90
|
+
});
|
|
91
|
+
for (const child of data.children) {
|
|
92
|
+
child.data[headerKey] = value;
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
export function setRank(sortOrder, dataList, headerKey, calcKey, measureList) {
|
|
97
|
+
const newDataList = [...dataList];
|
|
98
|
+
newDataList.sort((a, b) => {
|
|
99
|
+
let aValue = a.data[calcKey] || 0;
|
|
100
|
+
let bValue = b.data[calcKey] || 0;
|
|
101
|
+
if (aValue === bValue && measureList?.length > 1) {
|
|
102
|
+
for (let i = 1, leng = measureList.length; i < leng; i++) {
|
|
103
|
+
const item = measureList[i];
|
|
104
|
+
aValue = a.data[item.value] || 0;
|
|
105
|
+
bValue = b.data[item.value] || 0;
|
|
106
|
+
if (aValue !== bValue) {
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return sortOrder === 'ascend' ? aValue - bValue : bValue - aValue;
|
|
112
|
+
});
|
|
113
|
+
newDataList.forEach((item, index) => {
|
|
114
|
+
item.data[headerKey] = index + 1;
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
export function setGroupRank(type, headerKey, calcKey, tree, measureList) {
|
|
118
|
+
recursionForLastButTwo(tree, data => {
|
|
119
|
+
setRank(type, data.children, headerKey, calcKey, measureList);
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
export function setCustomRank(sortOrder, rankWay, dataList, headerKey, calcKey, measureList, rankDimList) {
|
|
123
|
+
// let newDataList = [...dataList];
|
|
124
|
+
if (rankDimList?.length) {
|
|
125
|
+
const tree = convertToTree(dataList, rankDimList.map(item => ({ key: item })), '总合计');
|
|
126
|
+
recursionForLastButTwo(tree, data => {
|
|
127
|
+
setCustomRankFunc(sortOrder, rankWay, data.children, headerKey, calcKey, measureList);
|
|
128
|
+
});
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
setCustomRankFunc(sortOrder, rankWay, dataList, headerKey, calcKey, measureList);
|
|
132
|
+
// newDataList.sort((a, b) => {
|
|
133
|
+
// let aValue = a.data[calcKey] || 0;
|
|
134
|
+
// let bValue = b.data[calcKey] || 0;
|
|
135
|
+
// if (aValue === bValue && measureList?.length > 1) {
|
|
136
|
+
// for (let i = 1, leng = measureList.length; i < leng; i++) {
|
|
137
|
+
// const item = measureList[i];
|
|
138
|
+
// aValue = a.data[item.value] || 0;
|
|
139
|
+
// bValue = b.data[item.value] || 0;
|
|
140
|
+
// if (aValue !== bValue) {
|
|
141
|
+
// break;
|
|
142
|
+
// }
|
|
143
|
+
// }
|
|
144
|
+
// }
|
|
145
|
+
// return sortOrder === 'ascend' ? aValue - bValue : bValue - aValue;
|
|
146
|
+
// });
|
|
147
|
+
// switch(rankWay) {
|
|
148
|
+
// // 不并列
|
|
149
|
+
// case 'NOT_ABREAST':
|
|
150
|
+
// newDataList.forEach((item, index) => {
|
|
151
|
+
// item.data[headerKey] = index + 1;
|
|
152
|
+
// })
|
|
153
|
+
// break;
|
|
154
|
+
// // 间隔并列
|
|
155
|
+
// case 'INTERVAL_ABREAST':
|
|
156
|
+
// newDataList.forEach((item, index) => {
|
|
157
|
+
// item.data[headerKey] = index + 1;
|
|
158
|
+
// if (
|
|
159
|
+
// index !== 0 &&
|
|
160
|
+
// (item.data[calcKey] || 0) === (newDataList[index - 1][calcKey] || 0)
|
|
161
|
+
// ) {
|
|
162
|
+
// item.data[headerKey] = newDataList[index - 1][headerKey];
|
|
163
|
+
// }
|
|
164
|
+
// })
|
|
165
|
+
// break;
|
|
166
|
+
// // 连续并列
|
|
167
|
+
// case 'CONTINUE_ABREAST':
|
|
168
|
+
// newDataList.forEach((item, index) => {
|
|
169
|
+
// if (index === 0) {
|
|
170
|
+
// item[headerKey] = index + 1;
|
|
171
|
+
// } else if (
|
|
172
|
+
// index !== 0 &&
|
|
173
|
+
// (item[calcKey] || 0) === (newDataList[index - 1][calcKey] || 0)
|
|
174
|
+
// ) {
|
|
175
|
+
// item[headerKey] = newDataList[index - 1][headerKey];
|
|
176
|
+
// } else if (
|
|
177
|
+
// index !== 0 &&
|
|
178
|
+
// (item[calcKey] || 0) !== (newDataList[index - 1][calcKey] || 0)
|
|
179
|
+
// ) {
|
|
180
|
+
// item[headerKey] = newDataList[index - 1][headerKey] + 1;
|
|
181
|
+
// }
|
|
182
|
+
// })
|
|
183
|
+
// break;
|
|
184
|
+
// default:
|
|
185
|
+
// break;
|
|
186
|
+
// }
|
|
187
|
+
}
|
|
188
|
+
export function setCustomRankFunc(sortOrder, rankWay, dataList, headerKey, calcKey, measureList) {
|
|
189
|
+
const newDataList = [...dataList];
|
|
190
|
+
newDataList.sort((a, b) => {
|
|
191
|
+
let aValue = a.data[calcKey] || 0;
|
|
192
|
+
let bValue = b.data[calcKey] || 0;
|
|
193
|
+
if (aValue === bValue && measureList?.length > 1) {
|
|
194
|
+
for (let i = 1, leng = measureList.length; i < leng; i++) {
|
|
195
|
+
const item = measureList[i];
|
|
196
|
+
aValue = a.data[item.value] || 0;
|
|
197
|
+
bValue = b.data[item.value] || 0;
|
|
198
|
+
if (aValue !== bValue) {
|
|
199
|
+
break;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
return sortOrder === 'ascend' ? aValue - bValue : bValue - aValue;
|
|
204
|
+
});
|
|
205
|
+
switch (rankWay) {
|
|
206
|
+
// 不并列
|
|
207
|
+
case 'NOT_ABREAST':
|
|
208
|
+
newDataList.forEach((item, index) => {
|
|
209
|
+
item.data[headerKey] = index + 1;
|
|
210
|
+
});
|
|
211
|
+
break;
|
|
212
|
+
// 间隔并列
|
|
213
|
+
case 'INTERVAL_ABREAST':
|
|
214
|
+
newDataList.forEach((item, index) => {
|
|
215
|
+
item.data[headerKey] = index + 1;
|
|
216
|
+
if (index !== 0 &&
|
|
217
|
+
(item.data[calcKey] || 0) === (newDataList[index - 1].data[calcKey] || 0)) {
|
|
218
|
+
item.data[headerKey] = newDataList[index - 1].data[headerKey];
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
break;
|
|
222
|
+
// 连续并列
|
|
223
|
+
case 'CONTINUE_ABREAST':
|
|
224
|
+
newDataList.forEach((item, index) => {
|
|
225
|
+
if (index === 0) {
|
|
226
|
+
item.data[headerKey] = index + 1;
|
|
227
|
+
}
|
|
228
|
+
else if (index !== 0 &&
|
|
229
|
+
(item.data[calcKey] || 0) === (newDataList[index - 1].data[calcKey] || 0)) {
|
|
230
|
+
item.data[headerKey] = newDataList[index - 1].data[headerKey];
|
|
231
|
+
}
|
|
232
|
+
else if (index !== 0 &&
|
|
233
|
+
(item.data[calcKey] || 0) !== (newDataList[index - 1].data[calcKey] || 0)) {
|
|
234
|
+
item.data[headerKey] = newDataList[index - 1].data[headerKey] + 1;
|
|
235
|
+
}
|
|
236
|
+
});
|
|
237
|
+
break;
|
|
238
|
+
default:
|
|
239
|
+
break;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
export function setGroupCustomRank(sortOrder, rankWay, tree, headerKey, calcKey, measureList, rankDimList) {
|
|
243
|
+
recursionForLastButTwo(tree, data => {
|
|
244
|
+
setCustomRank(sortOrder, rankWay, data.children, headerKey, calcKey, measureList, rankDimList);
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
// 获取倒数第二层的数据
|
|
248
|
+
export function recursionForLastButTwo(tree, callback) {
|
|
249
|
+
const recursionFn = (list) => {
|
|
250
|
+
for (const item of list) {
|
|
251
|
+
if (item.children?.length && item.children[0].children) {
|
|
252
|
+
recursionFn(item.children);
|
|
253
|
+
}
|
|
254
|
+
else if (item.children?.length && !item.children[0].children) {
|
|
255
|
+
callback(item);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
};
|
|
259
|
+
recursionFn(tree);
|
|
260
|
+
}
|
|
261
|
+
// 获取所有父节点,即合计行
|
|
262
|
+
export function recursionForParent(tree, callback) {
|
|
263
|
+
const recursionFn = (list) => {
|
|
264
|
+
for (const item of list) {
|
|
265
|
+
// 如果有子节点,先递归计算子节点
|
|
266
|
+
if (item.children?.length && item.children[0].children) {
|
|
267
|
+
recursionFn(item.children);
|
|
268
|
+
}
|
|
269
|
+
// 计算当前节点的值
|
|
270
|
+
if (item.children) {
|
|
271
|
+
callback(item);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
};
|
|
275
|
+
recursionFn(tree);
|
|
276
|
+
}
|
|
277
|
+
// 获取 sum({销售数量}) 的值
|
|
278
|
+
export function getSumExtra(header, data) {
|
|
279
|
+
const sum = {};
|
|
280
|
+
if (header.sumKeyList?.length) {
|
|
281
|
+
header.sumKeyList.forEach(sumKey => {
|
|
282
|
+
const topData = getTopData(data);
|
|
283
|
+
// 处理占比依赖其他计算度量的和的情况
|
|
284
|
+
if (!topData.sum || topData.sum[sumKey] === undefined) {
|
|
285
|
+
calcSum([topData], [{ key: sumKey }]);
|
|
286
|
+
}
|
|
287
|
+
sum[sumKey] = topData.sum?.[sumKey];
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
return sum;
|
|
291
|
+
}
|
|
292
|
+
// 获取分组占比合计值的 data
|
|
293
|
+
function getGroupParent(data, groupTotal) {
|
|
294
|
+
if (data.totalType === groupTotal) {
|
|
295
|
+
return data;
|
|
296
|
+
}
|
|
297
|
+
if (data.parent) {
|
|
298
|
+
return getGroupParent(data.parent, groupTotal);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
// 获取 group_sum({销售数量}) 的值
|
|
302
|
+
export function getGroupSumExtra(header, data) {
|
|
303
|
+
const sum = {};
|
|
304
|
+
let parent = null;
|
|
305
|
+
if (header.computeParam?.groupByList?.length) {
|
|
306
|
+
const { computeParam: { groupByList } } = header;
|
|
307
|
+
let sumOfGroup = null;
|
|
308
|
+
sumOfGroup = data.children
|
|
309
|
+
? groupByList.find(item => item.displayName === data.totalType)
|
|
310
|
+
: groupByList[groupByList.length - 1];
|
|
311
|
+
if (sumOfGroup?.groupTotal) {
|
|
312
|
+
parent = getGroupParent(data, sumOfGroup.groupTotal);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
if (header.groupSumKeyList?.length) {
|
|
316
|
+
header.groupSumKeyList.forEach(sumKey => {
|
|
317
|
+
// 处理分组占比依赖其他计算度量的和的情况
|
|
318
|
+
if (!data.parent?.sum || data.parent.sum[sumKey] === undefined) {
|
|
319
|
+
const topData = getTopData(data);
|
|
320
|
+
calcSum([topData], [{ key: sumKey }]);
|
|
321
|
+
}
|
|
322
|
+
if (parent && (!parent.sum || parent.sum[sumKey] === undefined)) {
|
|
323
|
+
const topData = getTopData(parent);
|
|
324
|
+
calcSum([topData], [{ key: sumKey }]);
|
|
325
|
+
}
|
|
326
|
+
sum[sumKey] = data.parent ? data.parent.sum[sumKey] : data.sum[sumKey];
|
|
327
|
+
if (parent) {
|
|
328
|
+
sum[sumKey] = parent.sum[sumKey];
|
|
329
|
+
}
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
return sum;
|
|
333
|
+
}
|
|
334
|
+
function setTreeSum(tree, header) {
|
|
335
|
+
for (const node of tree) {
|
|
336
|
+
sumDataByHeaderKey(node, header);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
function sumDataByHeaderKey(node, header) {
|
|
340
|
+
if (!node)
|
|
341
|
+
return 0;
|
|
342
|
+
const { key } = header;
|
|
343
|
+
let childrenSum = 0;
|
|
344
|
+
for (let child of node.children || []) {
|
|
345
|
+
childrenSum += sumDataByHeaderKey(child, header);
|
|
346
|
+
}
|
|
347
|
+
if (!node.children) {
|
|
348
|
+
return node.data[key] || 0;
|
|
349
|
+
}
|
|
350
|
+
else {
|
|
351
|
+
if (!node.sum) {
|
|
352
|
+
node.sum = {};
|
|
353
|
+
}
|
|
354
|
+
node.sum[key] = childrenSum;
|
|
355
|
+
return childrenSum;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
export function calcSum(tree, headerKeysList) {
|
|
359
|
+
for (const header of headerKeysList) {
|
|
360
|
+
setTreeSum(tree, header);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
export function getDateDate(params) {
|
|
364
|
+
const { header, data, headerKeysDic } = params;
|
|
365
|
+
const newData = { ...data.data };
|
|
366
|
+
const dateKeyList = [];
|
|
367
|
+
header.calcKeyList?.forEach(k => {
|
|
368
|
+
const h = headerKeysDic[k];
|
|
369
|
+
if (h?.dataType === 'DATE') {
|
|
370
|
+
dateKeyList.push(k);
|
|
371
|
+
}
|
|
372
|
+
});
|
|
373
|
+
if (dateKeyList?.length) {
|
|
374
|
+
dateKeyList.forEach(k => {
|
|
375
|
+
if (data.data[k]) {
|
|
376
|
+
newData[k] = differenceInDays(new Date(data.data[k]), new Date('1970-01-01'));
|
|
377
|
+
}
|
|
378
|
+
else {
|
|
379
|
+
newData[k] = undefined;
|
|
380
|
+
}
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
return newData;
|
|
384
|
+
}
|