Skip to content

Commit b78f776

Browse files
author
酥云
committed
fix(venn): 处理非法数据
1 parent f9433c0 commit b78f776

File tree

3 files changed

+115
-15
lines changed

3 files changed

+115
-15
lines changed

__tests__/unit/plots/venn/data-spec.ts

+47-13
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,53 @@ describe('venn 异常分支处理', () => {
1111
});
1212

1313
it('并集中,出现不存在的集合', () => {
14-
function render() {
15-
plot.changeData([
16-
{ sets: ['A'], size: 12, label: 'A' },
17-
{ sets: ['B'], size: 12, label: 'B' },
18-
{ sets: ['C'], size: 12, label: 'C' },
19-
{ sets: ['A', 'B'], size: 2, label: 'A&B' },
20-
{ sets: ['A', 'C'], size: 2, label: 'A&C' },
21-
{ sets: ['B', 'D'], size: 2, label: 'B&C' },
22-
{ sets: ['A', 'B', 'C'], size: 300 },
23-
]);
24-
}
25-
// 下个 pr 再处理
26-
expect(render).toThrowError();
14+
// @ts-ignore
15+
const fn = jest.fn();
16+
window.console.warn = fn;
17+
18+
plot.changeData([
19+
{ sets: ['A'], size: 12, label: 'A' },
20+
{ sets: ['C'], size: 12, label: 'C' },
21+
{ sets: ['A', 'B'], size: 2, label: 'A&B' },
22+
{ sets: ['A', 'C'], size: 2, label: 'A&C' },
23+
{ sets: ['B', 'D'], size: 2, label: 'B&C' },
24+
{ sets: ['A', 'B', 'C'], size: 30 },
25+
]);
26+
expect(fn).toBeCalledWith('AntV/G2Plot: warn: 交集中不能出现不存在的集合, 请输入合法数据');
27+
// @ts-ignore
28+
expect(plot.chart.options.data.length).toBe(3);
29+
30+
plot.changeData([
31+
{ sets: ['A'], size: 12, label: 'A' },
32+
{ sets: ['A', 'B'], size: 2, label: 'A&B' },
33+
{ sets: ['A', 'C'], size: 2, label: 'A&C' },
34+
{ sets: ['B', 'D'], size: 2, label: 'B&C' },
35+
{ sets: ['A', 'B', 'C'], size: 30 },
36+
]);
37+
expect(fn).toBeCalledWith('AntV/G2Plot: warn: 交集中不能出现不存在的集合, 请输入合法数据');
38+
// @ts-ignore
39+
expect(plot.chart.options.data.length).toBe(1);
40+
});
41+
42+
it('数据不为空', () => {
43+
// @ts-ignore
44+
const fn = jest.fn();
45+
window.console.warn = fn;
46+
47+
plot.changeData([]);
48+
expect(fn).toBeCalledWith('AntV/G2Plot: warn: 数据不能为空');
49+
// @ts-ignore
50+
expect(plot.chart.options.data.length).toBe(0);
51+
52+
plot.changeData(null);
53+
expect(fn).toBeCalledWith('AntV/G2Plot: warn: 数据不能为空');
54+
// @ts-ignore
55+
expect(plot.chart.options.data.length).toBe(0);
56+
57+
plot.changeData(undefined);
58+
expect(fn).toBeCalledWith('AntV/G2Plot: warn: 数据不能为空');
59+
// @ts-ignore
60+
expect(plot.chart.options.data.length).toBe(0);
2761
});
2862

2963
afterAll(() => {

src/plots/venn/adaptor.ts

+46-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import { Geometry } from '@antv/g2';
2-
import { isArray, get } from '@antv/util';
2+
import { isArray, get, deepMix, isEqual } from '@antv/util';
33
import { interaction, animation, theme, tooltip, scale } from '../../adaptor/common';
44
import { Params } from '../../core/adaptor';
55
import { schema as schemaGeometry } from '../../adaptor/geometries';
66
import { deepAssign, flow, getAdjustAppendPadding, normalPadding, resolveAllPadding } from '../../utils';
77
import { Datum } from '../../types';
8-
import { getColorMap, layoutVennData } from './utils';
8+
import { log, LEVEL } from '../../../src/utils';
9+
import { getColorMap, layoutVennData, islegalSets } from './utils';
910
import { CustomInfo, VennData, VennOptions } from './types';
1011
import { ID_FIELD } from './constant';
1112
import './shape';
@@ -50,6 +51,48 @@ function padding(params: Params<VennOptions>): Params<VennOptions> {
5051
return params;
5152
}
5253

54+
/**
55+
* 处理非法数据
56+
* @param params
57+
*/
58+
function data(params: Params<VennOptions>): Params<VennOptions> {
59+
const { options } = params;
60+
61+
/* 如遇到 交集 中存在 非法元素 的情况,就过滤掉
62+
* 如:
63+
* data = [
64+
* { sets: ['A'], size: 3 }, // 集合
65+
* { sets: ['B'], size: 4 }, // 集合
66+
* { sets: ['A', 'B'], size: 2 }, // 交集
67+
* { sets: ['A', 'B', 'C'], size: 2 }, // 交集 (存在非法 C,过滤该条数据)
68+
* ...
69+
* ]
70+
*/
71+
72+
let data = options['data'];
73+
if (!data) {
74+
log(LEVEL.WARN, false, 'warn: %s', '数据不能为空');
75+
data = [];
76+
}
77+
78+
// 合法元素的集合:['A', 'B']
79+
const currSets = data.filter((datum) => datum.sets.length === 1).map((datum) => datum.sets[0]);
80+
// 过滤 data
81+
const filterSets = data.filter((datum) => {
82+
const sets = datum.sets;
83+
// 存在非法元素,就过滤这条数据
84+
return islegalSets(currSets, sets);
85+
});
86+
87+
if (!isEqual(filterSets, data)) log(LEVEL.WARN, false, 'warn: %s', '交集中不能出现不存在的集合, 请输入合法数据');
88+
89+
return deepMix({}, params, {
90+
options: {
91+
data: filterSets,
92+
},
93+
});
94+
}
95+
5396
/**
5497
* geometry 处理
5598
* @param params
@@ -129,6 +172,7 @@ export function adaptor(params: Params<VennOptions>) {
129172
return flow(
130173
padding,
131174
theme,
175+
data,
132176
geometry,
133177
scale({}),
134178
legend,

src/plots/venn/utils.ts

+22
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { assign, memoize } from '@antv/util';
22
import { blend } from '../../utils/color/blend';
3+
import { log, LEVEL } from '../../../src/utils';
34
import { venn, scaleSolution } from './layout/layout';
45
import { circlePath, intersectionAreaPath, computeTextCentres } from './layout/diagram';
56
import { ID_FIELD, PATH_FIELD } from './constant';
@@ -46,6 +47,12 @@ export const getColorMap = memoize(
4647
export function layoutVennData(options: VennOptions, width: number, height: number, padding: number = 0): VennData {
4748
const { data, setsField, sizeField } = options;
4849

50+
// 处理空数据的情况
51+
if (data.length === 0) {
52+
log(LEVEL.WARN, false, 'warn: %s', '数据不能为空');
53+
return [];
54+
}
55+
4956
const vennData: VennData = data.map((d) => ({
5057
...d,
5158
sets: d[setsField] || [],
@@ -81,3 +88,18 @@ export function layoutVennData(options: VennOptions, width: number, height: numb
8188
});
8289
return vennData;
8390
}
91+
92+
/**
93+
* 检查是否存在 非法元素
94+
* @param legalArr 合法集合:['A', 'B']
95+
* @param testArr 检查集合:['A', 'B', 'C'] or ['A', 'C'](存在非法 'C')
96+
* @return boolean
97+
*/
98+
export function islegalSets(legalArr: any[], testArr: any[]): boolean {
99+
for (let i = 0; i < testArr.length; i++) {
100+
if (!legalArr.includes(testArr[i])) {
101+
return false;
102+
}
103+
}
104+
return true;
105+
}

0 commit comments

Comments
 (0)