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
package/constants.js
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
export const CALCULATED_REGEX = /\{(.+?)\}/g;
|
|
2
|
+
export const SUM_REGEX = /sum\((.+?)\)/g; // sum()匹配
|
|
3
|
+
export const GROUP_SUM_REGEX = /group_sum\((.+?)\)/g; // group_sum()匹配
|
|
4
|
+
export const GET_SIZE_REGEX = /getSize\((.+?)\)/g;
|
|
5
|
+
export const RANK_TYPES = [
|
|
6
|
+
{ label: '全局降序排名', value: 'GLOBAL_RANK_DESC' },
|
|
7
|
+
{ label: '全局升序排名', value: 'GLOBAL_RANK_ASC' },
|
|
8
|
+
{ label: '分组升序排名', value: 'GROUP_RANK_ASC' },
|
|
9
|
+
{ label: '分组降序排名', value: 'GROUP_RANK_DESC' },
|
|
10
|
+
{ label: '自定义排名', value: 'CUSTOM_RANK' },
|
|
11
|
+
];
|
|
12
|
+
// 累加等一次性算好全部的计算度量
|
|
13
|
+
export const ONCE_CALC_LIST = [
|
|
14
|
+
'GLOBAL_ACC',
|
|
15
|
+
'GROUP_ACC',
|
|
16
|
+
'MAX',
|
|
17
|
+
'MIN',
|
|
18
|
+
'GROUP_MAX',
|
|
19
|
+
'GROUP_MIN',
|
|
20
|
+
'AVG',
|
|
21
|
+
'AVG_NON_ZERO',
|
|
22
|
+
'GROUP_AVG',
|
|
23
|
+
'GROUP_AVG_NON_ZERO',
|
|
24
|
+
'GLOBAL_RANK_DESC',
|
|
25
|
+
'GLOBAL_RANK_ASC',
|
|
26
|
+
'GROUP_RANK_DESC',
|
|
27
|
+
'GROUP_RANK_ASC',
|
|
28
|
+
'CUSTOM_RANK',
|
|
29
|
+
];
|
|
30
|
+
// 合计已经算好的计算度量(data.current 中,如data.current['max' | 'avg' | 'sum'])
|
|
31
|
+
export const SUMMARY_ONCE_CALC_ALERADY_LIST = [
|
|
32
|
+
'GLOBAL_ACC',
|
|
33
|
+
'GROUP_ACC',
|
|
34
|
+
'MAX',
|
|
35
|
+
'MIN',
|
|
36
|
+
'GROUP_MAX',
|
|
37
|
+
'GROUP_MIN',
|
|
38
|
+
'AVG',
|
|
39
|
+
'AVG_NON_ZERO',
|
|
40
|
+
'GROUP_AVG',
|
|
41
|
+
'GROUP_AVG_NON_ZERO',
|
|
42
|
+
];
|
|
43
|
+
// 合计一次性算好全部的计算度量
|
|
44
|
+
// 不包括最大值/平均值等,因为这些在计算合计之前,已经在 data.current 上算好了
|
|
45
|
+
// 不包括累加,因为累加取最大值 data.curren.max 就可以了
|
|
46
|
+
export const SUMMARY_ONCE_CALC_LIST = [
|
|
47
|
+
'GLOBAL_RANK_DESC',
|
|
48
|
+
'GLOBAL_RANK_ASC',
|
|
49
|
+
'GROUP_RANK_DESC',
|
|
50
|
+
'GROUP_RANK_ASC',
|
|
51
|
+
'CUSTOM_RANK',
|
|
52
|
+
];
|
|
53
|
+
export const DEFAULT_FORMAT = {
|
|
54
|
+
// type: 'number',
|
|
55
|
+
type: 'default',
|
|
56
|
+
precision: 0,
|
|
57
|
+
quantityUnit: '个',
|
|
58
|
+
unitSuffix: '',
|
|
59
|
+
isThousandth: true,
|
|
60
|
+
progressColor: 'rgba(0, 0, 0, 0)',
|
|
61
|
+
hideZero: false,
|
|
62
|
+
};
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { getCalcRowValue } from "./calc-measure/calc-measure-hander";
|
|
2
|
+
import { recursionForParent } from "./calc-measure/utils";
|
|
3
|
+
import { RANK_TYPES, SUMMARY_ONCE_CALC_ALERADY_LIST, SUMMARY_ONCE_CALC_LIST } from "./constants";
|
|
4
|
+
import { calcCustomAgg } from "./ez-custom-agg-func/ez-custom-agg-func-hander";
|
|
5
|
+
import { getFuncValue } from "./func";
|
|
6
|
+
import { getSameLevelList } from "./utils";
|
|
7
|
+
// export type TAggFunc = 'SUM' | 'MEDIAN' | 'AVG' | 'AVG_NON_ZERO' | 'MAX' | 'MIN' | 'COUNT' | 'DISTINC COUNT' | 'DISTINC_COUNT' | 'CUSTOM';
|
|
8
|
+
// 合计方式
|
|
9
|
+
const EzAggFuncHandler = {
|
|
10
|
+
'SUM': (params) => {
|
|
11
|
+
const { data, calcKey, aggRange } = params;
|
|
12
|
+
if (aggRange && aggRange !== 'GLOBAL') {
|
|
13
|
+
const list = getSameLevelList(data, aggRange);
|
|
14
|
+
return getFuncValue({
|
|
15
|
+
aggKey: 'SUM',
|
|
16
|
+
dataList: list,
|
|
17
|
+
header: { key: calcKey }
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
return data?.current?.sum[calcKey];
|
|
21
|
+
},
|
|
22
|
+
'MEDIAN': (params) => {
|
|
23
|
+
const { data, calcKey, dataList, aggRange } = params;
|
|
24
|
+
if (aggRange && aggRange !== 'GLOBAL') {
|
|
25
|
+
const list = getSameLevelList(data, aggRange);
|
|
26
|
+
return getFuncValue({
|
|
27
|
+
aggKey: 'MEDIAN',
|
|
28
|
+
dataList: list,
|
|
29
|
+
header: { key: calcKey }
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
const arr = [...dataList].sort();
|
|
33
|
+
const len = arr.length;
|
|
34
|
+
if (len % 2 === 1) {
|
|
35
|
+
return arr[(len - 1) / 2].data[calcKey];
|
|
36
|
+
}
|
|
37
|
+
return (arr[len / 2].data[calcKey] + arr[len / 2 - 1].data[calcKey]) / 2;
|
|
38
|
+
},
|
|
39
|
+
// 最大值
|
|
40
|
+
'MAX': (params) => {
|
|
41
|
+
const { calcKey, data, aggRange, dataList } = params;
|
|
42
|
+
if (aggRange && aggRange !== 'GLOBAL') {
|
|
43
|
+
const list = getSameLevelList(data, aggRange);
|
|
44
|
+
return getFuncValue({
|
|
45
|
+
aggKey: 'MAX',
|
|
46
|
+
dataList: list,
|
|
47
|
+
header: { key: calcKey }
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
if (!data) {
|
|
51
|
+
return getFuncValue({
|
|
52
|
+
aggKey: 'MAX',
|
|
53
|
+
dataList: dataList,
|
|
54
|
+
header: { key: calcKey }
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
return data?.current?.max[calcKey];
|
|
58
|
+
},
|
|
59
|
+
// 最小值
|
|
60
|
+
'MIN': (params) => {
|
|
61
|
+
const { calcKey, data, aggRange, dataList } = params;
|
|
62
|
+
if (aggRange && aggRange !== 'GLOBAL') {
|
|
63
|
+
const list = getSameLevelList(data, aggRange);
|
|
64
|
+
return getFuncValue({
|
|
65
|
+
aggKey: 'MIN',
|
|
66
|
+
dataList: list,
|
|
67
|
+
header: { key: calcKey }
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
if (!data) {
|
|
71
|
+
return getFuncValue({
|
|
72
|
+
aggKey: 'MIN',
|
|
73
|
+
dataList: dataList,
|
|
74
|
+
header: { key: calcKey }
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
return data?.current?.min[calcKey];
|
|
78
|
+
},
|
|
79
|
+
// 平均值
|
|
80
|
+
'AVG': (params) => {
|
|
81
|
+
const { calcKey, data, aggRange, dataList } = params;
|
|
82
|
+
if (aggRange && aggRange !== 'GLOBAL') {
|
|
83
|
+
const list = getSameLevelList(data, aggRange);
|
|
84
|
+
return getFuncValue({
|
|
85
|
+
aggKey: 'AVG',
|
|
86
|
+
dataList: list,
|
|
87
|
+
header: { key: calcKey }
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
if (!data) {
|
|
91
|
+
return getFuncValue({
|
|
92
|
+
aggKey: 'AVG',
|
|
93
|
+
dataList: dataList,
|
|
94
|
+
header: { key: calcKey }
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
return data?.current?.avg[calcKey];
|
|
98
|
+
},
|
|
99
|
+
// 平均值非零
|
|
100
|
+
'AVG_NON_ZERO': (params) => {
|
|
101
|
+
const { calcKey, data, aggRange, dataList } = params;
|
|
102
|
+
if (aggRange && aggRange !== 'GLOBAL') {
|
|
103
|
+
const list = getSameLevelList(data, aggRange);
|
|
104
|
+
return getFuncValue({
|
|
105
|
+
aggKey: 'AVG_NON_ZERO',
|
|
106
|
+
dataList: list,
|
|
107
|
+
header: { key: calcKey }
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
if (!data) {
|
|
111
|
+
return getFuncValue({
|
|
112
|
+
aggKey: 'AVG_NON_ZERO',
|
|
113
|
+
dataList: dataList,
|
|
114
|
+
header: { key: calcKey }
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
return data?.current?.avg_non_zero[calcKey];
|
|
118
|
+
},
|
|
119
|
+
// 计数
|
|
120
|
+
'COUNT': (params) => {
|
|
121
|
+
const { data, calcKey, dataList, aggRange } = params;
|
|
122
|
+
if (aggRange && aggRange !== 'GLOBAL') {
|
|
123
|
+
const list = getSameLevelList(data, aggRange);
|
|
124
|
+
return getFuncValue({
|
|
125
|
+
aggKey: 'COUNT',
|
|
126
|
+
dataList: list,
|
|
127
|
+
header: { key: calcKey }
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
return dataList.length;
|
|
131
|
+
},
|
|
132
|
+
// 非重复计数
|
|
133
|
+
'DISTINC_COUNT': (params) => {
|
|
134
|
+
const set = new Set();
|
|
135
|
+
const { calcKey, dataList } = params;
|
|
136
|
+
for (const item of dataList) {
|
|
137
|
+
set.add(item.data[calcKey]);
|
|
138
|
+
}
|
|
139
|
+
return set.size;
|
|
140
|
+
},
|
|
141
|
+
// 非重复计数(老)
|
|
142
|
+
'DISTINC COUNT': (params) => {
|
|
143
|
+
const set = new Set();
|
|
144
|
+
const { calcKey, dataList } = params;
|
|
145
|
+
for (const item of dataList) {
|
|
146
|
+
set.add(item.data[calcKey]);
|
|
147
|
+
}
|
|
148
|
+
return set.size;
|
|
149
|
+
},
|
|
150
|
+
// 计算值
|
|
151
|
+
'CUSTOM': (params) => {
|
|
152
|
+
const { header, header: { key, measureType, calcKeyList }, headerKeysDic, data, calcKey, dataList, tree, } = params;
|
|
153
|
+
if (SUMMARY_ONCE_CALC_ALERADY_LIST.includes(measureType)) {
|
|
154
|
+
recursionForParent(tree, data => {
|
|
155
|
+
// return calcCustomAgg({...params, data});
|
|
156
|
+
data.data[key] = calcCustomAgg({ ...params, data });
|
|
157
|
+
});
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
if (SUMMARY_ONCE_CALC_LIST.includes(measureType)) {
|
|
161
|
+
calcCustomAgg(params);
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
if (RANK_TYPES.some(item => item.value === measureType)) {
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
// 'SUM', 'DIFFERENCE', 'DIVISION', 'RATE', 'RATIO', 'GROUP_RATIO'
|
|
168
|
+
return getCalcRowValue({
|
|
169
|
+
header,
|
|
170
|
+
headerKeysDic,
|
|
171
|
+
data,
|
|
172
|
+
dataList,
|
|
173
|
+
});
|
|
174
|
+
},
|
|
175
|
+
// 不显示合计
|
|
176
|
+
'NOT_SHOW': (params) => {
|
|
177
|
+
return null;
|
|
178
|
+
},
|
|
179
|
+
};
|
|
180
|
+
export function calcAgg(params) {
|
|
181
|
+
const { aggKey } = params;
|
|
182
|
+
if (EzAggFuncHandler[aggKey]) {
|
|
183
|
+
return EzAggFuncHandler[aggKey](params);
|
|
184
|
+
}
|
|
185
|
+
return 0;
|
|
186
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { getTopData } from "../calc-measure/utils";
|
|
2
|
+
import { setTotalCustomRank, setTotalGloalRank, setTotalGroupRank } from "./utils";
|
|
3
|
+
// 合计方式:计算值
|
|
4
|
+
const EZCustomAggFuncHandler = {
|
|
5
|
+
'GLOBAL_ACC': (params) => {
|
|
6
|
+
const { data, calcKey, } = params;
|
|
7
|
+
return data.current?.max[calcKey];
|
|
8
|
+
},
|
|
9
|
+
'GROUP_ACC': (params) => {
|
|
10
|
+
const { data, calcKey, } = params;
|
|
11
|
+
return data.current?.max[calcKey];
|
|
12
|
+
},
|
|
13
|
+
'MAX': (params) => {
|
|
14
|
+
const { header: { calcKeyList }, data, } = params;
|
|
15
|
+
const topData = getTopData(data);
|
|
16
|
+
return topData.current?.max[calcKeyList[0]];
|
|
17
|
+
},
|
|
18
|
+
'MIN': (params) => {
|
|
19
|
+
const { header: { calcKeyList }, data, } = params;
|
|
20
|
+
const topData = getTopData(data);
|
|
21
|
+
return topData.current?.min[calcKeyList[0]];
|
|
22
|
+
},
|
|
23
|
+
'GROUP_MAX': (params) => {
|
|
24
|
+
const { header: { calcKeyList }, data, } = params;
|
|
25
|
+
return data.current?.max[calcKeyList[0]];
|
|
26
|
+
},
|
|
27
|
+
'GROUP_MIN': (params) => {
|
|
28
|
+
const { header: { calcKeyList }, data, } = params;
|
|
29
|
+
return data.current?.min[calcKeyList[0]];
|
|
30
|
+
},
|
|
31
|
+
'AVG': (params) => {
|
|
32
|
+
const { header: { calcKeyList }, data, } = params;
|
|
33
|
+
const topData = getTopData(data);
|
|
34
|
+
return topData.current?.avg[calcKeyList[0]];
|
|
35
|
+
},
|
|
36
|
+
'AVG_NON_ZERO': (params) => {
|
|
37
|
+
const { header: { calcKeyList }, data, } = params;
|
|
38
|
+
const topData = getTopData(data);
|
|
39
|
+
return topData.current?.avg_non_zero[calcKeyList[0]];
|
|
40
|
+
},
|
|
41
|
+
'GROUP_AVG': (params) => {
|
|
42
|
+
const { header: { calcKeyList }, data, } = params;
|
|
43
|
+
return data.current?.avg[calcKeyList[0]];
|
|
44
|
+
},
|
|
45
|
+
'GROUP_AVG_NON_ZERO': (params) => {
|
|
46
|
+
const { header: { calcKeyList }, data, } = params;
|
|
47
|
+
return data.current?.avg_non_zero[calcKeyList[0]];
|
|
48
|
+
},
|
|
49
|
+
'GLOBAL_RANK_DESC': (params) => {
|
|
50
|
+
setTotalGloalRank(params);
|
|
51
|
+
},
|
|
52
|
+
'GLOBAL_RANK_ASC': (params) => {
|
|
53
|
+
setTotalGloalRank(params);
|
|
54
|
+
},
|
|
55
|
+
'GROUP_RANK_DESC': (params) => {
|
|
56
|
+
setTotalGroupRank(params);
|
|
57
|
+
},
|
|
58
|
+
'GROUP_RANK_ASC': (params) => {
|
|
59
|
+
setTotalGroupRank(params);
|
|
60
|
+
},
|
|
61
|
+
'CUSTOM_RANK': (params) => {
|
|
62
|
+
setTotalCustomRank(params);
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
export function calcCustomAgg(params) {
|
|
66
|
+
const { header: { measureType }, } = params;
|
|
67
|
+
if (EZCustomAggFuncHandler[measureType]) {
|
|
68
|
+
return EZCustomAggFuncHandler[measureType](params);
|
|
69
|
+
}
|
|
70
|
+
return 0;
|
|
71
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { recursionForParent, setCustomRank } from "../calc-measure/utils";
|
|
2
|
+
import { getSameLevelArrOfTotal } from "../utils";
|
|
3
|
+
export function setTotalGloalRank(params) {
|
|
4
|
+
const { header: { key, measureType, calcKeyList }, tree, } = params;
|
|
5
|
+
const arr = getSameLevelArrOfTotal(tree);
|
|
6
|
+
arr.forEach(sameLevelList => {
|
|
7
|
+
const list = [...sameLevelList];
|
|
8
|
+
list.sort((a, b) => {
|
|
9
|
+
const aValue = a.data[calcKeyList[0]] || 0;
|
|
10
|
+
const bValue = b.data[calcKeyList[0]] || 0;
|
|
11
|
+
if (measureType === 'GLOBAL_RANK_DESC') {
|
|
12
|
+
return bValue - aValue;
|
|
13
|
+
}
|
|
14
|
+
return aValue - bValue;
|
|
15
|
+
});
|
|
16
|
+
list.forEach((item, index) => {
|
|
17
|
+
item.data[key] = index + 1;
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
export function setTotalGroupRank(params) {
|
|
22
|
+
const { header: { key, measureType, calcKeyList }, tree, } = params;
|
|
23
|
+
recursionForParent(tree, data => {
|
|
24
|
+
const children = [...data.children];
|
|
25
|
+
children.sort((a, b) => {
|
|
26
|
+
const aValue = a.data[calcKeyList[0]] || 0;
|
|
27
|
+
const bValue = b.data[calcKeyList[0]] || 0;
|
|
28
|
+
if (measureType === 'GROUP_RANK_DESC') {
|
|
29
|
+
return bValue - aValue;
|
|
30
|
+
}
|
|
31
|
+
return aValue - bValue;
|
|
32
|
+
});
|
|
33
|
+
children.forEach((item, index) => {
|
|
34
|
+
item.data[key] = index + 1;
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
export function setTotalCustomRank(params) {
|
|
39
|
+
const { header: { key, measureType, calcKeyList, computeParam, computeParam: { sortOrder, rankTarget, rankWay, rankDimList }, }, tree, } = params;
|
|
40
|
+
if (rankTarget === 'GLOBAL') {
|
|
41
|
+
const arr = getSameLevelArrOfTotal(tree);
|
|
42
|
+
arr.forEach(sameLevelList => {
|
|
43
|
+
setCustomRank(sortOrder, rankWay, sameLevelList, key, calcKeyList[0], computeParam?.measureList, computeParam?.rankDimList);
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
switch (rankTarget) {
|
|
47
|
+
case 'GLOBAL':
|
|
48
|
+
const arr = getSameLevelArrOfTotal(tree);
|
|
49
|
+
arr.forEach(sameLevelList => {
|
|
50
|
+
setCustomRank(sortOrder, rankWay, sameLevelList, key, calcKeyList[0], computeParam?.measureList, computeParam?.rankDimList);
|
|
51
|
+
});
|
|
52
|
+
break;
|
|
53
|
+
case 'GROUP':
|
|
54
|
+
recursionForParent(tree, data => {
|
|
55
|
+
setCustomRank(sortOrder, rankWay, data.children, key, calcKeyList[0], computeParam?.measureList, computeParam?.rankDimList);
|
|
56
|
+
});
|
|
57
|
+
break;
|
|
58
|
+
default:
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
61
|
+
}
|
package/ezNumber.js
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { DEFAULT_FORMAT } from "./constants";
|
|
2
|
+
import { format as dateFormat, parseISO } from 'date-fns';
|
|
3
|
+
import { getFormatUnit, formatNumber as customFormatNumber } from "./utils";
|
|
4
|
+
import { formatPercent } from "./angular/formatPercent";
|
|
5
|
+
import { formatNumber } from "./angular/formatNumber";
|
|
6
|
+
export function ezNumber(num, format = 'number', digitsInfo = '1.0-2', defaultValue = '-', customFormat = null, isCondition = false) {
|
|
7
|
+
if (['IMAGE', 'LINK'].includes(format)) {
|
|
8
|
+
format = typeof num;
|
|
9
|
+
}
|
|
10
|
+
if (num === '允许空') {
|
|
11
|
+
return '';
|
|
12
|
+
}
|
|
13
|
+
if (isCondition && isNaN(num)) {
|
|
14
|
+
return num;
|
|
15
|
+
}
|
|
16
|
+
if (!format) {
|
|
17
|
+
format = 'number';
|
|
18
|
+
}
|
|
19
|
+
if (!digitsInfo) {
|
|
20
|
+
digitsInfo = '1.0-2';
|
|
21
|
+
}
|
|
22
|
+
format = format.toLowerCase();
|
|
23
|
+
if (format === 'date' || format === 'string') {
|
|
24
|
+
if (format === 'date' && num && num !== -Infinity && num !== Infinity && num !== '-' && num !== '无' && num !== '未定义') {
|
|
25
|
+
return dateFormat(typeof num === 'number' ? new Date(num) : parseISO(num), customFormat?.format || 'yyyy-MM-dd');
|
|
26
|
+
}
|
|
27
|
+
return num ?? defaultValue;
|
|
28
|
+
}
|
|
29
|
+
if (num === null || !isFinite(num)) {
|
|
30
|
+
return defaultValue;
|
|
31
|
+
}
|
|
32
|
+
if (format === null || format === undefined) {
|
|
33
|
+
format = 'number';
|
|
34
|
+
}
|
|
35
|
+
if (customFormat?.hideZero && num === 0) {
|
|
36
|
+
return '';
|
|
37
|
+
}
|
|
38
|
+
if (customFormat) {
|
|
39
|
+
const newFormat = customFormat || { ...DEFAULT_FORMAT };
|
|
40
|
+
let newNum = `${num}`;
|
|
41
|
+
if (newFormat.type === 'number' && newFormat.quantityUnit !== '个') {
|
|
42
|
+
newNum = getFormatUnit(newNum, newFormat.quantityUnit);
|
|
43
|
+
}
|
|
44
|
+
if (newFormat.type === 'percent') {
|
|
45
|
+
newNum = `${Number(newNum) * 100}`;
|
|
46
|
+
}
|
|
47
|
+
newNum = customFormatNumber(newNum, newFormat.precision, newFormat.isThousandth);
|
|
48
|
+
if (newFormat.type === 'percent') {
|
|
49
|
+
newNum += '%';
|
|
50
|
+
}
|
|
51
|
+
if (newFormat.unitSuffix) {
|
|
52
|
+
newNum += newFormat.unitSuffix;
|
|
53
|
+
}
|
|
54
|
+
return newNum;
|
|
55
|
+
}
|
|
56
|
+
if (format === 'percent') {
|
|
57
|
+
return formatPercent(num, 'zh-CN', digitsInfo);
|
|
58
|
+
}
|
|
59
|
+
if (format === 'thousand') {
|
|
60
|
+
return num < 1000 ?
|
|
61
|
+
formatNumber(num, 'zh-CN', digitsInfo) :
|
|
62
|
+
`${formatNumber(num / 1000, 'zh-CN', digitsInfo)}k`;
|
|
63
|
+
}
|
|
64
|
+
if (format === 'currency') {
|
|
65
|
+
const K = 1000;
|
|
66
|
+
const M = K * K;
|
|
67
|
+
const B = K * M;
|
|
68
|
+
if (num < K) {
|
|
69
|
+
return formatNumber(num, 'zh-CN', digitsInfo);
|
|
70
|
+
}
|
|
71
|
+
else if (num < M) {
|
|
72
|
+
return `${formatNumber(num / K, 'zh-CN', digitsInfo)}K`;
|
|
73
|
+
}
|
|
74
|
+
else if (num < B) {
|
|
75
|
+
return `${formatNumber(num / M, 'zh-CN', digitsInfo)}M`;
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
return `${formatNumber(num / B, 'zh-CN', digitsInfo)}B`;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return formatNumber(num, 'zh-CN', digitsInfo);
|
|
82
|
+
}
|
package/func.js
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
const func = {
|
|
2
|
+
'SUM': (params) => {
|
|
3
|
+
const { dataList, header } = params;
|
|
4
|
+
return dataList.reduce((total, item) => total + (item.data[header.key] || 0), 0);
|
|
5
|
+
},
|
|
6
|
+
'MEDIAN': (params) => {
|
|
7
|
+
const { dataList, header: { key } } = params;
|
|
8
|
+
const arr = [...dataList].sort((a, b) => (a.data[key] || 0) - (b.data[key] || 0));
|
|
9
|
+
const len = arr.length;
|
|
10
|
+
if (len % 2 === 1) {
|
|
11
|
+
return arr[(len - 1) / 2].data[key];
|
|
12
|
+
}
|
|
13
|
+
return (arr[len / 2].data[key] + arr[len / 2 - 1].data[key]) / 2;
|
|
14
|
+
},
|
|
15
|
+
'MAX': (params) => {
|
|
16
|
+
const { dataList, header } = params;
|
|
17
|
+
let max = -Infinity;
|
|
18
|
+
for (const item of dataList) {
|
|
19
|
+
max = Math.max(max, item.data[header.key] || 0);
|
|
20
|
+
}
|
|
21
|
+
return max;
|
|
22
|
+
},
|
|
23
|
+
'MIN': (params) => {
|
|
24
|
+
const { dataList, header } = params;
|
|
25
|
+
let min = Infinity;
|
|
26
|
+
for (const item of dataList) {
|
|
27
|
+
min = Math.min(min, item.data[header.key] || 0);
|
|
28
|
+
}
|
|
29
|
+
return min;
|
|
30
|
+
},
|
|
31
|
+
'AVG': (params) => {
|
|
32
|
+
const { dataList, header } = params;
|
|
33
|
+
const sum = dataList.reduce((total, item) => total + (item.data[header.key] || 0), 0);
|
|
34
|
+
return sum / dataList.length;
|
|
35
|
+
},
|
|
36
|
+
// 平均值非零
|
|
37
|
+
'AVG_NON_ZERO': (params) => {
|
|
38
|
+
const { dataList, header } = params;
|
|
39
|
+
let sum = 0;
|
|
40
|
+
let leng = 0;
|
|
41
|
+
for (const item of dataList) {
|
|
42
|
+
if (item.data[header.key]) {
|
|
43
|
+
sum += item.data[header.key];
|
|
44
|
+
leng++;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return sum / leng;
|
|
48
|
+
},
|
|
49
|
+
// 计数
|
|
50
|
+
'COUNT': (params) => {
|
|
51
|
+
const { dataList, header } = params;
|
|
52
|
+
return dataList.length;
|
|
53
|
+
},
|
|
54
|
+
// 非重复计数
|
|
55
|
+
'DISTINC_COUNT': (params) => {
|
|
56
|
+
const { dataList, header: { key } } = params;
|
|
57
|
+
const set = new Set();
|
|
58
|
+
for (const item of dataList) {
|
|
59
|
+
set.add(item.data[key]);
|
|
60
|
+
}
|
|
61
|
+
return set.size;
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
export function getFuncValue(params) {
|
|
65
|
+
const { aggKey } = params;
|
|
66
|
+
if (func[aggKey]) {
|
|
67
|
+
return func[aggKey](params);
|
|
68
|
+
}
|
|
69
|
+
return 0;
|
|
70
|
+
}
|
package/index.js
ADDED
package/interface.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "yi-bi-ez-table",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "yi-bi table",
|
|
5
|
+
"license": "ISC",
|
|
6
|
+
"author": "yi-bi",
|
|
7
|
+
"type": "commonjs",
|
|
8
|
+
"main": "index.js",
|
|
9
|
+
"scripts": {
|
|
10
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"bignumber.js": "^9.3.1",
|
|
14
|
+
"lodash": "^4.17.21"
|
|
15
|
+
}
|
|
16
|
+
}
|
package/prisma/seed.js
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// import { PrismaClient, Prisma } from '@prisma/client'
|
|
2
|
+
//
|
|
3
|
+
// const prisma = new PrismaClient()
|
|
4
|
+
//
|
|
5
|
+
// const userData: Prisma.UserCreateInput[] = [
|
|
6
|
+
// {
|
|
7
|
+
// name: 'Alice',
|
|
8
|
+
// email: 'alice@prisma.io',
|
|
9
|
+
// posts: {
|
|
10
|
+
// create: [
|
|
11
|
+
// {
|
|
12
|
+
// title: 'Join the Prisma Slack',
|
|
13
|
+
// content: 'https://slack.prisma.io',
|
|
14
|
+
// published: true,
|
|
15
|
+
// },
|
|
16
|
+
// ],
|
|
17
|
+
// },
|
|
18
|
+
// },
|
|
19
|
+
// {
|
|
20
|
+
// name: 'Nilu',
|
|
21
|
+
// email: 'nilu@prisma.io',
|
|
22
|
+
// posts: {
|
|
23
|
+
// create: [
|
|
24
|
+
// {
|
|
25
|
+
// title: 'Follow Prisma on Twitter',
|
|
26
|
+
// content: 'https://www.twitter.com/prisma',
|
|
27
|
+
// published: true,
|
|
28
|
+
// },
|
|
29
|
+
// ],
|
|
30
|
+
// },
|
|
31
|
+
// },
|
|
32
|
+
// {
|
|
33
|
+
// name: 'Mahmoud',
|
|
34
|
+
// email: 'mahmoud@prisma.io',
|
|
35
|
+
// posts: {
|
|
36
|
+
// create: [
|
|
37
|
+
// {
|
|
38
|
+
// title: 'Ask a question about Prisma on GitHub',
|
|
39
|
+
// content: 'https://www.github.com/prisma/prisma/discussions',
|
|
40
|
+
// published: true,
|
|
41
|
+
// },
|
|
42
|
+
// {
|
|
43
|
+
// title: 'Prisma on YouTube',
|
|
44
|
+
// content: 'https://pris.ly/youtube',
|
|
45
|
+
// },
|
|
46
|
+
// ],
|
|
47
|
+
// },
|
|
48
|
+
// },
|
|
49
|
+
// ]
|
|
50
|
+
//
|
|
51
|
+
// async function main() {
|
|
52
|
+
// console.log(`Start seeding ...`)
|
|
53
|
+
// for (const u of userData) {
|
|
54
|
+
// const user = await prisma.user.create({
|
|
55
|
+
// data: u,
|
|
56
|
+
// })
|
|
57
|
+
// console.log(`Created user with id: ${user.id}`)
|
|
58
|
+
// }
|
|
59
|
+
// console.log(`Seeding finished.`)
|
|
60
|
+
// }
|
|
61
|
+
//
|
|
62
|
+
// main()
|
|
63
|
+
// .then(async () => {
|
|
64
|
+
// await prisma.$disconnect()
|
|
65
|
+
// })
|
|
66
|
+
// .catch(async (e) => {
|
|
67
|
+
// console.error(e)
|
|
68
|
+
// await prisma.$disconnect()
|
|
69
|
+
// process.exit(1)
|
|
70
|
+
// })
|