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/utils.js ADDED
@@ -0,0 +1,910 @@
1
+ import { addMonths, addYears, differenceInMonths, differenceInYears, format, parseISO } from "date-fns";
2
+ import { CALCULATED_REGEX } from "./constants";
3
+ import _ from "lodash";
4
+ import BigNumber from "bignumber.js";
5
+ export const DATA_TYPE_MAP = {
6
+ 0: 'NUMBER',
7
+ 1: 'STRING',
8
+ 2: 'DATE',
9
+ '-1': 'IMAGE',
10
+ '-2': 'LINK',
11
+ };
12
+ export function transformChn(str) {
13
+ // 将单引号‘’都转换成',将双引号“”都转换成"
14
+ str = str.replace(/\’|\‘/g, '\'').replace(/\“|\”/g, '"');
15
+ // 将中括号【】转换成[],将大括号{}转换成{}, 将()转换成()
16
+ str = str.replace(/\【/g, '[').replace(/\】/g, ']').replace(/\{/g, '{').replace(/\}/g, '}').replace(/\(/g, '(').replace(/\)/g, ')');
17
+ // 将逗号,转换成,,将:转换成:
18
+ str = str.replace(/,/g, ',').replace(/:/g, ':');
19
+ return str;
20
+ }
21
+ // 中文符号转换成英文符号
22
+ export function chnToEn(chineseChar) {
23
+ const originalExpr = chineseChar;
24
+ const fields = originalExpr?.match(CALCULATED_REGEX);
25
+ let expr = transformChn(chineseChar);
26
+ if (fields?.length) {
27
+ fields.forEach(item => {
28
+ const str = transformChn(item);
29
+ // {变量} 中的转义转换回去
30
+ expr = expr.replaceAll(str, item);
31
+ });
32
+ }
33
+ return expr;
34
+ }
35
+ // 获取起止日期间的所有日期
36
+ export function getDateList(startDate, endDate, formatStr = 'yyyy-MM-dd') {
37
+ const dateList = [];
38
+ const oneDay = 24 * 60 * 60 * 1000;
39
+ let s = startDate.getTime();
40
+ const e = endDate.getTime();
41
+ while (s <= e) {
42
+ dateList.push(format(new Date(s), formatStr));
43
+ s += oneDay;
44
+ }
45
+ return dateList;
46
+ }
47
+ // 获取起止年份间的所有年份
48
+ export function getYearList(startYear, endYear, formatStr = 'yyyy') {
49
+ const years = differenceInYears(endYear, startYear);
50
+ const yearList = [];
51
+ for (let i = 0; i <= years; i++) {
52
+ yearList.push(format(addYears(startYear, i), formatStr));
53
+ }
54
+ return yearList;
55
+ }
56
+ // 获取起止月份间的所有月份
57
+ export function getMonthList(startMonth, endMonth, formatStr = 'yyyy-MM') {
58
+ const months = differenceInMonths(endMonth, startMonth);
59
+ const monthList = [];
60
+ for (let i = 0; i <= months; i++) {
61
+ monthList.push(format(addMonths(startMonth, i), formatStr));
62
+ }
63
+ return monthList;
64
+ }
65
+ export function getMeasureDataType(data) {
66
+ if (data.measureType === 'CONDITION') {
67
+ if (data.hasOwnProperty('vtype')) {
68
+ return (DATA_TYPE_MAP[data.vtype] || 'STRING');
69
+ }
70
+ return 'STRING';
71
+ }
72
+ if (data.format && data.format.type === 'percent') {
73
+ return 'PERCENT';
74
+ }
75
+ if (data.expr) {
76
+ return 'NUMBER';
77
+ }
78
+ return (DATA_TYPE_MAP[data.vtype] || 'STRING');
79
+ }
80
+ export const getStyleType = (format) => {
81
+ if (format &&
82
+ ((format.type === 'percent' && (!format.styleType || format.styleType === 'progress')) ||
83
+ format.styleType === 'progress')) {
84
+ return 'progress';
85
+ }
86
+ if (format &&
87
+ format.showTrend &&
88
+ (format.type === 'number' ||
89
+ (format.type === 'percent' && format.styleType && format.styleType === 'trend'))) {
90
+ return 'trend';
91
+ }
92
+ return null;
93
+ };
94
+ export function getCatchFunction(expr) {
95
+ let func = null;
96
+ try {
97
+ func = new Function('data', expr);
98
+ }
99
+ catch (error) {
100
+ func = null;
101
+ }
102
+ return func;
103
+ }
104
+ // 表达式转函数体
105
+ export function expr2FnBody(expr) {
106
+ return expr.includes('return') ? expr : `return ${expr}`;
107
+ }
108
+ export function deepRenameExprKey(measureList, isRenameExpr = true) {
109
+ // const deepRenameExpr = (list: Array<IDisplayMeasure>, oldExprKey: string, newExprKey: string) => {
110
+ // if (list && list.length) {
111
+ // const regex = new RegExp(_.escapeRegExp(oldExprKey), 'g');
112
+ // list.forEach(item => {
113
+ // if (item.expr && item.expr.includes(oldExprKey)) {
114
+ // item.expr = item.expr.replace(regex, newExprKey);
115
+ // } else if (item.isGroup && item.children && item.children.length) {
116
+ // deepRenameExpr(item.children, oldExprKey, newExprKey);
117
+ // }
118
+ // });
119
+ // }
120
+ // };
121
+ // const deepRenameExprKey = (list: Array<IDisplayMeasure>, exprKey: string) => {
122
+ // if (list && list.length) {
123
+ // list.forEach(item => {
124
+ // if (!item.isGroup) {
125
+ // let newExprKey = exprKey ? `${exprKey}[${item.displayName}` : item.displayName;
126
+ // // const prefixArr = newExprKey.split('[');
127
+ // // if (prefixArr && prefixArr.length) {
128
+ // // for (let i = 0, leng = prefixArr.length - 1; i < leng; i++) {
129
+ // // newExprKey += ']';
130
+ // // }
131
+ // // }
132
+ // newExprKey += ']'.repeat(newExprKey.split('[').length - 1);
133
+ // if (newExprKey !== item.exprKey) {
134
+ // const oldExprKey = item.exprKey;
135
+ // item.exprKey = newExprKey;
136
+ // if (isRenameExpr) {
137
+ // deepRenameExpr(measureList, `{${oldExprKey}}`, `{${newExprKey}}`);
138
+ // }
139
+ // }
140
+ // }
141
+ // if (item.children && item.children.length) {
142
+ // deepRenameExprKey(item.children, exprKey ? `${exprKey}[${item.displayName}` : item.displayName);
143
+ // }
144
+ // });
145
+ // }
146
+ // };
147
+ // deepRenameExprKey(measureList, '');
148
+ deepChildrenOfRename(measureList, isRenameExpr, measureList, '');
149
+ }
150
+ function deepRenameExpr(list, oldExprKey, newExprKey) {
151
+ if (list && list.length) {
152
+ const regex = new RegExp(_.escapeRegExp(oldExprKey), 'g');
153
+ list.forEach(item => {
154
+ if (item.expr && item.expr.includes(oldExprKey)) {
155
+ item.expr = item.expr.replace(regex, newExprKey);
156
+ }
157
+ else if (item.isGroup && item.children && item.children.length) {
158
+ deepRenameExpr(item.children, oldExprKey, newExprKey);
159
+ }
160
+ });
161
+ }
162
+ }
163
+ function deepChildrenOfRename(measureList, isRenameExpr, list, exprKey) {
164
+ if (list && list.length) {
165
+ list.forEach(item => {
166
+ if (!item.isGroup) {
167
+ let newExprKey = exprKey ? `${exprKey}[${item.displayName}` : item.displayName;
168
+ // const prefixArr = newExprKey.split('[');
169
+ // if (prefixArr && prefixArr.length) {
170
+ // for (let i = 0, leng = prefixArr.length - 1; i < leng; i++) {
171
+ // newExprKey += ']';
172
+ // }
173
+ // }
174
+ newExprKey += ']'.repeat(newExprKey.split('[').length - 1);
175
+ if (newExprKey !== item.exprKey) {
176
+ const oldExprKey = item.exprKey;
177
+ item.exprKey = newExprKey;
178
+ if (isRenameExpr) {
179
+ deepRenameExpr(measureList, `{${oldExprKey}}`, `{${newExprKey}}`);
180
+ }
181
+ }
182
+ }
183
+ if (item.children && item.children.length) {
184
+ deepChildrenOfRename(measureList, isRenameExpr, item.children, exprKey ? `${exprKey}[${item.displayName}` : item.displayName);
185
+ }
186
+ });
187
+ }
188
+ }
189
+ export function getStyleConditionFn(style, conditionList, key, dataType) {
190
+ conditionList = _.cloneDeep(conditionList);
191
+ let fn = `
192
+ let style = {
193
+ color: "${style.color}",
194
+ backgroundColor: "${style.backgroundColor}",
195
+ fontWeight: "${style && style.bold ? 'bold' : null}",
196
+ fontStyle: "${style && style.italic ? 'italic' : null}",
197
+ textDecoration: "${style && style.underline ? 'underline' : null}",
198
+ fontSize: "${style && style.fontSize ? (style.fontSize + 'px') : null}",
199
+ textAlign: "${style && style.horizontalAlign ? style.horizontalAlign : null}",
200
+ childStyle: {
201
+ textDecoration: "${style && style.strike ? 'line-through' : null}",
202
+ }
203
+ };
204
+ let value = data.data["${key}"];
205
+ if (!((value || value === 0) && value !== '-')) {
206
+ value = 0;
207
+ }
208
+ `;
209
+ let value = `(data.data["${key}"] || 0)`;
210
+ conditionList?.forEach(c => {
211
+ let isExpr = false;
212
+ if (c.value) {
213
+ let formual = c.value;
214
+ const fields = c.value?.match(CALCULATED_REGEX);
215
+ if (fields && fields.length) {
216
+ isExpr = true;
217
+ for (let fI = 0, fLeng = fields.length; fI < fLeng; fI++) {
218
+ const f = fields[fI];
219
+ const str = `(data.data[${'"' + (f.substring(1, f.length - 1)) + '"'}] || 0)`;
220
+ formual = formual.replace(f, str);
221
+ }
222
+ c.value = formual;
223
+ }
224
+ }
225
+ if (!isExpr && dataType === 'DATE') {
226
+ c.value = format(new Date(c.value), 'yyyy-MM-dd');
227
+ value = format(new Date(`data.data["${key}"]`), 'yyyy-MM-dd');
228
+ }
229
+ let condition = ('"' + value + '"') + c.op + (!isExpr && isFinite(c.value) ? Number(c.value) : ('"' + c.value + '"'));
230
+ if (c.op !== 'expr') {
231
+ if (['NUMBER', 'PERCENT'].includes(dataType)) {
232
+ condition = (value) + c.op + (c.value);
233
+ }
234
+ if (dataType === 'STRING') {
235
+ // @ts-ignore
236
+ condition = (value) + c.op + ('"' + c.value + '"');
237
+ }
238
+ }
239
+ else if (dataType !== 'DATE') {
240
+ condition = c.value;
241
+ }
242
+ fn += `
243
+ if (${condition}) {
244
+ style = {
245
+ color: "${c.color}",
246
+ backgroundColor: "${c.backgroundColor}",
247
+ fontWeight: "${c && c.bold ? 'bold' : null}",
248
+ fontStyle: "${c && c.italic ? 'italic' : null}",
249
+ textDecoration: "${c && c.underline ? 'underline' : null}",
250
+ fontSize: "${c && c.fontSize ? (c.fontSize + 'px') : null}",
251
+ textAlign: "${c && c.horizontalAlign ? c.horizontalAlign : null}",
252
+ childStyle: {
253
+ textDecoration: "${c && c.strike ? 'line-through' : null}",
254
+ }
255
+ }
256
+ }
257
+ `;
258
+ });
259
+ fn += `
260
+ return style;
261
+ `;
262
+ return fn;
263
+ }
264
+ // 设置样式 computeFn
265
+ export function setStyleComputeFn(header) {
266
+ // const { color, backgroundColor } = header;
267
+ const dataType = header.dataType;
268
+ header.styleComputeFn = getCatchFunction(getStyleConditionFn(header.style, header.styleConditionList, header.key, dataType));
269
+ }
270
+ // 数字计算 NaN,Infinity,-Infinity 返回 0
271
+ export function getNotNaNValue(value) {
272
+ return Object.is(value, NaN) || [Infinity, -Infinity].includes(value) ? 0 : value;
273
+ }
274
+ // 函数计算
275
+ export function getCalcValue(computeFn, data) {
276
+ let value = null;
277
+ try {
278
+ value = computeFn(data);
279
+ }
280
+ catch (error) {
281
+ console.log(error);
282
+ }
283
+ value = getNotNaNValue(value);
284
+ return value;
285
+ }
286
+ export function getSize(measure, data, headerKeysDic) {
287
+ const item = data.data;
288
+ const header = headerKeysDic[measure];
289
+ let size = '';
290
+ if (!item || !header || !header.groupList || !header.groupList.length) {
291
+ return size;
292
+ }
293
+ const index = header.groupList.indexOf(item['尺码组']);
294
+ const keys = header.key.split('[');
295
+ keys[keys.length - 1] = keys[keys.length - 1].replaceAll(']', '');
296
+ size = keys[index + 1];
297
+ size = size === 'null' ? '允许空' : size;
298
+ return size;
299
+ }
300
+ export function getDifferentTypeHeaderKeys(headerKeys) {
301
+ const dimKeyList = [];
302
+ const measureKeyList = [];
303
+ const groupKeyList = [];
304
+ const normalMeasureKeyList = [];
305
+ for (const h of headerKeys) {
306
+ if (h.type === 'DIM') {
307
+ dimKeyList.push(h);
308
+ }
309
+ if (h.type === 'MEASURE') {
310
+ measureKeyList.push(h);
311
+ if (!h.measureType || h.measureType === 'NORMAL') {
312
+ normalMeasureKeyList.push(h);
313
+ }
314
+ }
315
+ if (h.groupBy) {
316
+ groupKeyList.push(h);
317
+ }
318
+ }
319
+ return {
320
+ dimKeyList,
321
+ measureKeyList,
322
+ groupKeyList,
323
+ normalMeasureKeyList,
324
+ };
325
+ }
326
+ export const sortNotFinite = (aValue, bValue) => {
327
+ if (!isFinite(aValue) && isFinite(bValue)) {
328
+ return 1;
329
+ }
330
+ if (!isFinite(bValue) && isFinite(aValue)) {
331
+ return -1;
332
+ }
333
+ return 0;
334
+ };
335
+ function chineseNumToArabicNum(str) {
336
+ const numMap = {
337
+ '一': 1,
338
+ '二': 2,
339
+ '三': 3,
340
+ '四': 4,
341
+ '五': 5,
342
+ '六': 6,
343
+ '七': 7,
344
+ '八': 8,
345
+ '九': 9,
346
+ '十': 10,
347
+ };
348
+ const replacedStr = str.replace(/[一二三四五六七八九十]/g, (match) => numMap[match]);
349
+ const numbers = replacedStr.match(/\d+/g);
350
+ return {
351
+ replacedStr,
352
+ num: numbers ? Number(numbers.join('')) : null,
353
+ };
354
+ }
355
+ const chineseNum = ['一', '二', '三', '四', '五', '六', '七', '八', '九', '十'];
356
+ export function setSortDataList(dataList, sortList, headerKeysDic, isChangeList = false) {
357
+ // const newDataList = isChangeList ? dataList : [...dataList];
358
+ // sortList?.forEach(sort => {
359
+ // let key = '';
360
+ // const displayNameList = [...sort.displayNameList];
361
+ // if (sort.displayNameList && sort.displayNameList.length && ['维度', '度量'].includes(sort.displayNameList[0])) {
362
+ // displayNameList.shift();
363
+ // }
364
+ // displayNameList?.forEach(item => {
365
+ // key = key ? `${key}[${item}` : item;
366
+ // });
367
+ // for (let i = 0, leng = displayNameList?.length; i < leng - 1; i++) {
368
+ // key += ']';
369
+ // }
370
+ // const dataType = headerKeysDic[key]?.dataType;
371
+ // if (dataType) {
372
+ // newDataList.sort((a, b) => {
373
+ // let aValue = a.data[key];
374
+ // let bValue = b.data[key];
375
+ // if (['NUMBER', 'PERCENT'].includes(dataType)) {
376
+ // switch (sort.value) {
377
+ // case 'ascend':
378
+ // const sortIsFiniteAscend = sortNotFinite(aValue, bValue);
379
+ // if (sortIsFiniteAscend) {
380
+ // return sortIsFiniteAscend;
381
+ // }
382
+ // return aValue - bValue;
383
+ // case 'descend':
384
+ // const sortIsFiniteDescend = sortNotFinite(aValue, bValue);
385
+ // if (sortIsFiniteDescend) {
386
+ // return sortIsFiniteDescend;
387
+ // }
388
+ // return bValue - aValue;
389
+ // default:
390
+ // return 0;
391
+ // }
392
+ // }
393
+ // if (dataType === 'DATE') {
394
+ // switch (sort.value) {
395
+ // case 'ascend':
396
+ // return parseISO(aValue).getTime() - parseISO(bValue).getTime();
397
+ // case 'descend':
398
+ // return parseISO(bValue).getTime() - parseISO(aValue).getTime();
399
+ // default:
400
+ // return 0;
401
+ // }
402
+ // }
403
+ // if ((aValue || aValue === 0) && typeof aValue === 'number') {
404
+ // aValue = `${aValue}`;
405
+ // }
406
+ // if ((bValue || bValue === 0) && typeof bValue === 'number') {
407
+ // bValue = `${bValue}`;
408
+ // }
409
+ // let aIncludes = false;
410
+ // for (const item of chineseNum) {
411
+ // if (aValue?.includes(item)) {
412
+ // aIncludes = true;
413
+ // break;
414
+ // }
415
+ // }
416
+ // let bIncludes = false;
417
+ // for (const item of chineseNum) {
418
+ // if (bValue?.includes(item)) {
419
+ // bIncludes = true;
420
+ // break;
421
+ // }
422
+ // }
423
+ // const c = aValue;
424
+ // if (aIncludes && bIncludes) {
425
+ // aValue = chineseNumToArabicNum(aValue).num;
426
+ // bValue = chineseNumToArabicNum(bValue).num;
427
+ // return sort.value === 'ascend' ? aValue - bValue : bValue - aValue;
428
+ // // return result;
429
+ // }
430
+ // switch (sort.value) {
431
+ // case 'ascend':
432
+ // return aValue?.localeCompare(bValue);
433
+ // case 'descend':
434
+ // return bValue?.localeCompare(aValue);
435
+ // default:
436
+ // return 0;
437
+ // }
438
+ // });
439
+ // }
440
+ // });
441
+ const newDataList = isChangeList ? dataList : [...dataList];
442
+ newDataList.sort((a, b) => {
443
+ for (const sort of sortList) {
444
+ let key = '';
445
+ const displayNameList = [...sort.displayNameList];
446
+ if (sort.displayNameList && sort.displayNameList.length && ['维度', '度量'].includes(sort.displayNameList[0])) {
447
+ displayNameList.shift();
448
+ }
449
+ displayNameList?.forEach(item => {
450
+ key = key ? `${key}[${item}` : item;
451
+ });
452
+ for (let i = 0, leng = displayNameList?.length; i < leng - 1; i++) {
453
+ key += ']';
454
+ }
455
+ const dataType = headerKeysDic[key]?.dataType;
456
+ if (dataType) {
457
+ // let aValue = a.data?.[key] ?? a[key];
458
+ // let bValue = b.data?.[key] ?? b[key];
459
+ let aValue = getParentValue(a, headerKeysDic[key]);
460
+ let bValue = getParentValue(b, headerKeysDic[key]);
461
+ let result = 0;
462
+ if (['NUMBER', 'PERCENT'].includes(dataType)) {
463
+ // result = sortNotFinite(aValue, bValue);
464
+ // if (result !== 0) return result;
465
+ aValue = aValue || 0;
466
+ bValue = bValue || 0;
467
+ result = sort.value === 'ascend' ? aValue - bValue : bValue - aValue;
468
+ }
469
+ else if (dataType === 'DATE') {
470
+ const aTime = aValue ? (typeof aValue === 'number' ? aValue : parseISO(aValue).getTime()) : 0;
471
+ const bTime = bValue ? (typeof bValue === 'number' ? bValue : parseISO(bValue).getTime()) : 0;
472
+ // console.log('sort date',aTime,bTime);
473
+ result = sort.value === 'ascend' ? aTime - bTime : bTime - aTime;
474
+ }
475
+ else {
476
+ if ((aValue || aValue === 0) && typeof aValue === 'number') {
477
+ aValue = `${aValue}`;
478
+ }
479
+ if ((bValue || bValue === 0) && typeof bValue === 'number') {
480
+ bValue = `${bValue}`;
481
+ }
482
+ // let aIncludes = false;
483
+ // for (const item of chineseNum) {
484
+ // if (aValue?.includes(item)) {
485
+ // aIncludes = true;
486
+ // break;
487
+ // }
488
+ // }
489
+ // let bIncludes = false;
490
+ // for (const item of chineseNum) {
491
+ // if (bValue?.includes(item)) {
492
+ // bIncludes = true;
493
+ // break;
494
+ // }
495
+ // }
496
+ // const c = aValue;
497
+ // if (aIncludes && bIncludes) {
498
+ // aValue = chineseNumToArabicNum(aValue).num;
499
+ // bValue = chineseNumToArabicNum(bValue).num;
500
+ // result = sort.value === 'ascend' ? aValue - bValue : bValue - aValue;
501
+ // } else {
502
+ result = sort.value === 'ascend' ? aValue?.localeCompare(bValue) : bValue?.localeCompare(aValue);
503
+ // }
504
+ }
505
+ if (result !== 0)
506
+ return result;
507
+ }
508
+ }
509
+ return 0;
510
+ });
511
+ const hasVertical = newDataList?.[0].same?.index || newDataList?.[0].same?.index === 0;
512
+ if (hasVertical) {
513
+ sameIndexSort(newDataList);
514
+ }
515
+ return newDataList;
516
+ }
517
+ function sameIndexSort(arr) {
518
+ const keysIndices = new Map(Array.from(new Set(arr.map(item => item.same.index))).map((key, i) => [key, i]));
519
+ const originalIndices = new Map(arr.map((item, i) => [item, i]));
520
+ arr.sort((a, b) => {
521
+ const aIndex = keysIndices.get(a.same.index);
522
+ const bIndex = keysIndices.get(b.same.index);
523
+ if (aIndex !== bIndex) {
524
+ return aIndex - bIndex;
525
+ }
526
+ return Number(originalIndices.get(a)) - Number(originalIndices.get(b));
527
+ });
528
+ return arr;
529
+ ;
530
+ }
531
+ export function getImageDisplayName(src) {
532
+ let name = src;
533
+ if (src?.includes('/')) {
534
+ name = src.split('/').pop();
535
+ if (name.includes('%2F')) {
536
+ name = name.split('%2F').pop();
537
+ }
538
+ }
539
+ return name;
540
+ }
541
+ // 删除 tree 中存在 children 属性但是 children 为空的节点
542
+ export function pruneEmptyChildren(tree) {
543
+ for (let i = tree.length - 1; i >= 0; i--) {
544
+ const node = tree[i];
545
+ if (node.children) {
546
+ if (node.children.length === 0) {
547
+ tree.splice(i, 1);
548
+ }
549
+ else {
550
+ pruneEmptyChildren(node.children);
551
+ if (node.children.length === 0) {
552
+ tree.splice(i, 1);
553
+ }
554
+ }
555
+ }
556
+ }
557
+ return tree;
558
+ }
559
+ export function calcCachedData(dataList, headerKeysDic, cachedData) {
560
+ const calcMaxAndMin = (dataList, headerKeysDic, cachedData) => {
561
+ for (const data of dataList) {
562
+ if (data.children && data.children.length) {
563
+ calcMaxAndMin(data.children, headerKeysDic, cachedData);
564
+ }
565
+ for (const key in cachedData) {
566
+ if (cachedData.hasOwnProperty(key)) {
567
+ const header = headerKeysDic[key];
568
+ const value = data.data[key];
569
+ if (header && value !== undefined && value !== null) {
570
+ if (header.measureType === 'MAX') {
571
+ if (!cachedData[key].MAX || cachedData[key].MAX < value) {
572
+ cachedData[key].MAX = value;
573
+ }
574
+ }
575
+ if (header.measureType === 'MIN') {
576
+ if (!cachedData[key].MIN || cachedData[key].MIN > value) {
577
+ cachedData[key].MIN = value;
578
+ }
579
+ }
580
+ }
581
+ }
582
+ }
583
+ }
584
+ };
585
+ calcMaxAndMin(dataList, headerKeysDic, cachedData);
586
+ }
587
+ function setCurrentGroup(tree, header) {
588
+ const { key, dataType } = header;
589
+ const groupDataByHeaderKey = (list) => {
590
+ for (const item of list) {
591
+ if (item.children?.length && item.children[0].children) {
592
+ groupDataByHeaderKey(item.children);
593
+ }
594
+ if (item.children) {
595
+ // let max = -Infinity;
596
+ // let min = Infinity;
597
+ let max = undefined;
598
+ let min = undefined;
599
+ // let total = 0;
600
+ // let totalNonZero = 0;
601
+ let childrenSum = 0;
602
+ let leng = 0;
603
+ let lengNonZero = 0;
604
+ for (const child of item.children) {
605
+ let value = child.data[key];
606
+ if (dataType === 'DATE' && value) {
607
+ value = parseISO(value).getTime();
608
+ }
609
+ childrenSum += item.children.length && item.children[0].children ? child.current.sum[key] : (value || 0);
610
+ leng += item.children.length && item.children[0].children ? child.current.leng[key] : 1;
611
+ lengNonZero += item.children.length && item.children[0].children ? child.current.lengNonZero[key] : (value ? 1 : 0);
612
+ let maxValue = item.children.length && item.children[0].children ? child.current.max[key] : value;
613
+ let minValue = item.children.length && item.children[0].children ? child.current.min[key] : value;
614
+ if (max === undefined || maxValue > max) {
615
+ max = maxValue;
616
+ }
617
+ if (min === undefined || minValue < min) {
618
+ min = minValue;
619
+ }
620
+ }
621
+ if (!item.current) {
622
+ item.current = {};
623
+ }
624
+ if (!item.current.sum) {
625
+ item.current.sum = {};
626
+ }
627
+ if (!item.current.avg) {
628
+ item.current.avg = {};
629
+ }
630
+ if (!item.current.avg_non_zero) {
631
+ item.current.avg_non_zero = {};
632
+ }
633
+ if (!item.current.leng) {
634
+ item.current.leng = {};
635
+ }
636
+ if (!item.current.lengNonZero) {
637
+ item.current.lengNonZero = {};
638
+ }
639
+ if (!item.current.max) {
640
+ item.current.max = {};
641
+ }
642
+ if (!item.current.min) {
643
+ item.current.min = {};
644
+ }
645
+ item.current.max[key] = max;
646
+ item.current.min[key] = min;
647
+ item.current.sum[key] = childrenSum;
648
+ item.current.leng[key] = leng;
649
+ item.current.lengNonZero[key] = lengNonZero;
650
+ item.current.avg[key] = childrenSum / leng;
651
+ item.current.avg_non_zero[key] = childrenSum / lengNonZero;
652
+ }
653
+ }
654
+ };
655
+ groupDataByHeaderKey(tree);
656
+ }
657
+ // 计算每个分组的最大值、最小值、平均值、平均值非零
658
+ export function calcCurrentGroup(tree, headerKeysList) {
659
+ for (const header of headerKeysList) {
660
+ setCurrentGroup(tree, header);
661
+ }
662
+ }
663
+ export function getSameLevelArrOfTotal(tree) {
664
+ // const sameLevelArr = [];
665
+ // const getSameLevel = (list, level: number = 0) => {
666
+ // for (const item of list) {
667
+ // if (item.children) {
668
+ // if (!sameLevelArr[level]) {
669
+ // sameLevelArr[level] = [];
670
+ // }
671
+ // sameLevelArr[level].push(item);
672
+ // getSameLevel(item.children, level + 1);
673
+ // }
674
+ // }
675
+ // }
676
+ // getSameLevel(tree);
677
+ // return sameLevelArr;
678
+ return getSameLevel(tree);
679
+ }
680
+ const getSameLevel = (list, level = 0, sameLevelArr = []) => {
681
+ for (const item of list) {
682
+ if (item.children) {
683
+ if (!sameLevelArr[level]) {
684
+ sameLevelArr[level] = [];
685
+ }
686
+ sameLevelArr[level].push(item);
687
+ getSameLevel(item.children, level + 1, sameLevelArr);
688
+ }
689
+ }
690
+ return sameLevelArr;
691
+ };
692
+ export function getAlertConditionFn(conditionList, headerKeys) {
693
+ conditionList = _.cloneDeep(conditionList);
694
+ let expression = '';
695
+ conditionList?.forEach((c, i) => {
696
+ let isExpr = false;
697
+ if (c.value) {
698
+ let formual = c.value;
699
+ const fields = c.value?.match(CALCULATED_REGEX);
700
+ if (fields && fields.length) {
701
+ isExpr = true;
702
+ for (let fI = 0, fLeng = fields.length; fI < fLeng; fI++) {
703
+ const f = fields[fI];
704
+ const str = `(data.data[${'"' + (f.substring(1, f.length - 1)) + '"'}] || 0)`;
705
+ formual = formual.replace(f, str);
706
+ }
707
+ c.value = formual;
708
+ }
709
+ }
710
+ const header = headerKeys.find(item => item.key === c.displayName);
711
+ let value = `(data.data["${header.key}"] || 0)`;
712
+ if (!isExpr && header.dataType === 'DATE') {
713
+ c.value = format(new Date(c.value), 'yyyy-MM-dd');
714
+ value = format(new Date(`data.data["${header.key}"]`), 'yyyy-MM-dd');
715
+ }
716
+ let condition = ('"' + value + '"') + c.op + (!isExpr && isFinite(c.value) ? Number(c.value) : ('"' + c.value + '"'));
717
+ if (c.op !== 'expr') {
718
+ if (['NUMBER', 'PERCENT'].includes(header.dataType)) {
719
+ condition = (value) + c.op + (c.value);
720
+ }
721
+ if (header.dataType === 'STRING') {
722
+ // @ts-ignore
723
+ condition = (value) + c.op + ('"' + c.value + '"');
724
+ }
725
+ }
726
+ else if (header.dataType !== 'DATE') {
727
+ condition = c.value;
728
+ }
729
+ expression += i === 0 ? condition : ` && ${condition}`;
730
+ });
731
+ const fn = `
732
+ let boolean = false;
733
+ if (${expression}) {
734
+ boolean = true;
735
+ }
736
+ return boolean;
737
+ `;
738
+ return fn;
739
+ }
740
+ // 度量单位格式化
741
+ export function getFormatUnit(num, unit) {
742
+ let newNum = Number(num);
743
+ switch (unit) {
744
+ case '万':
745
+ newNum = new BigNumber(newNum).dividedBy(10000).toNumber();
746
+ break;
747
+ case '百万':
748
+ newNum = new BigNumber(newNum).dividedBy(1000000).toNumber();
749
+ break;
750
+ case '亿':
751
+ newNum = new BigNumber(newNum).dividedBy(100000000).toNumber();
752
+ break;
753
+ default:
754
+ break;
755
+ }
756
+ return `${newNum}`;
757
+ }
758
+ /**
759
+ * 数字格式化
760
+ * num: 数字或字符串
761
+ * cent: 小数位数
762
+ * isThousand: 是否千分位
763
+ * 返回字符串
764
+ */
765
+ export function formatNumber(num, cent, isThousand) {
766
+ let newNum = Number(num);
767
+ if (isNaN(newNum)) {
768
+ return `${num}`;
769
+ }
770
+ const sign = (Number(newNum) === (newNum = Math.abs(newNum)));
771
+ newNum = Math.floor(newNum * Math.pow(10, cent) + 0.50000000001);
772
+ let cents = newNum % Math.pow(10, cent);
773
+ newNum = Math.floor(newNum / Math.pow(10, cent)).toString();
774
+ cents = cents.toString();
775
+ while (cents.length < cent) {
776
+ cents = '0' + cents;
777
+ }
778
+ if (isThousand) {
779
+ for (let i = 0; i < Math.floor((newNum.length - (1 + i)) / 3); i++) {
780
+ newNum = newNum.substring(0, newNum.length - (4 * i + 3)) + ',' + newNum.substring(newNum.length - (4 * i + 3));
781
+ }
782
+ }
783
+ return cent > 0 ? (((sign) ? '' : '-') + newNum + '.' + cents) : (((sign) ? '' : '-') + newNum);
784
+ }
785
+ function deepCopy(obj) {
786
+ // 检查传入参数的类型
787
+ if (typeof obj !== "object" || obj === null) {
788
+ return obj; // 对于非对象类型直接返回
789
+ }
790
+ // 创建一个空对象或数组,用于存储深拷贝后的结果
791
+ const copy = Array.isArray(obj) ? [] : {};
792
+ for (let key in obj) {
793
+ if (key !== 'parent' && Object.prototype.hasOwnProperty.call(obj, key)) {
794
+ // 递归调用deepCopy进行深拷贝
795
+ copy[key] = deepCopy(obj[key]);
796
+ }
797
+ }
798
+ return copy;
799
+ }
800
+ export function cloneDeepTree(tree, parent = null) {
801
+ const copiedTree = [];
802
+ for (let i = 0; i < tree.length; i++) {
803
+ const node = tree[i];
804
+ const copiedNode = {
805
+ parent: parent
806
+ };
807
+ for (const key in node) {
808
+ if (key !== 'children' && key !== 'parent') {
809
+ const prop = node[key];
810
+ if (typeof prop === 'object' && prop !== null) {
811
+ copiedNode[key] = deepCopy(prop);
812
+ }
813
+ else {
814
+ copiedNode[key] = prop;
815
+ }
816
+ }
817
+ }
818
+ if (node.children?.length > 0) {
819
+ copiedNode.children = cloneDeepTree(node.children, copiedNode);
820
+ }
821
+ copiedTree.push(copiedNode);
822
+ }
823
+ return copiedTree;
824
+ }
825
+ export function getSameLevelList(data, aggRange) {
826
+ const list = [];
827
+ const stack = [];
828
+ if (data.children?.length) {
829
+ stack.push(...data.children);
830
+ }
831
+ while (stack.length) {
832
+ const item = stack.pop();
833
+ if (item.totalType === aggRange) {
834
+ list.push(item);
835
+ }
836
+ else if (item.children?.length) {
837
+ stack.push(...item.children);
838
+ }
839
+ }
840
+ return list;
841
+ }
842
+ export function convertToTree(dataList, groupKeyList, firstDimKey) {
843
+ // const groupKeyList = this.groupKeyList;
844
+ const root = {
845
+ children: [],
846
+ value: "合计",
847
+ data: { [firstDimKey]: "合计" },
848
+ totalType: 'TOTAL_SUMMARY',
849
+ };
850
+ const nodeMap = { root }; // 哈希表存储节点
851
+ for (const data of dataList) {
852
+ let currentNode = root;
853
+ let nodeId = "root";
854
+ for (let i = 0; i < groupKeyList.length; i++) {
855
+ const group = groupKeyList[i];
856
+ const value = data.data[group.key];
857
+ nodeId = `${nodeId}_${value}`;
858
+ let matchingNode = nodeMap[nodeId];
859
+ if (!matchingNode) {
860
+ matchingNode = {
861
+ nodeId,
862
+ value,
863
+ children: [],
864
+ data: { [group.key]: value },
865
+ totalType: group.key,
866
+ };
867
+ currentNode.children.push(matchingNode);
868
+ nodeMap[nodeId] = matchingNode;
869
+ }
870
+ currentNode = matchingNode;
871
+ }
872
+ currentNode.children.push({ data: data.data });
873
+ }
874
+ const makeTreeFn = (list, parent = null) => {
875
+ for (const item of list) {
876
+ delete item.nodeId;
877
+ item.parent = parent;
878
+ if (item.children?.length) {
879
+ makeTreeFn(item.children, item);
880
+ }
881
+ }
882
+ };
883
+ const tree = [root];
884
+ makeTreeFn(tree);
885
+ return tree;
886
+ }
887
+ export function getWeekName(time, showZhou = false) {
888
+ let weekDay = ['星期天', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
889
+ if (showZhou) {
890
+ weekDay = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
891
+ }
892
+ const myDate = new Date(Date.parse(time));
893
+ return weekDay[myDate.getDay()];
894
+ }
895
+ export function getParentValue(data, header) {
896
+ const key = header.key;
897
+ let value = data.data?.[key] ?? data[key];
898
+ if (header.type === 'MEASURE' || data.data.hasOwnProperty(key) || data.hasOwnProperty(key)) {
899
+ return value;
900
+ }
901
+ let parent = data.parent;
902
+ while (parent) {
903
+ value = parent.data?.[key];
904
+ if (parent.data?.hasOwnProperty(key)) {
905
+ break;
906
+ }
907
+ parent = parent.parent;
908
+ }
909
+ return value;
910
+ }