@publishfx/publish-chart 2.1.7 → 2.1.9

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/CHANGELOG.md CHANGED
@@ -1,3 +1,21 @@
1
+ **2.1.9** feat(chart): 组合图折线色彩设置
2
+ - 2026-03-04T16:45:43+08:00 [feat(chart): 组合图折线色彩设置](http://lf.git.oa.mt/publish_platform/web/publish/commit/2d456a5bd13fbed534b125a71955e8d18f62bbfc)
3
+ - 2026-03-04T16:42:51+08:00 [feat(chart): 组合图副轴最大值逻辑复原](http://lf.git.oa.mt/publish_platform/web/publish/commit/6a1e758f64f6e7ef202c8089afecdd49580cf133)
4
+ - 2026-03-04T16:28:16+08:00 [fix(chart): 解决缺数据场景下的tooltip问题](http://lf.git.oa.mt/publish_platform/web/publish/commit/163c2e4e4ca33c92179a505b18f8f4e03d4d5229)
5
+ - 2026-03-04T16:18:04+08:00 [feat(chart): 固定组合图副轴最大值](http://lf.git.oa.mt/publish_platform/web/publish/commit/1dde15ae135b27676db7d57940dee63fb0c7d4cb)
6
+ - 2026-03-04T16:06:17+08:00 [fix(chart): 修复空数据导致的tooltip异常问题](http://lf.git.oa.mt/publish_platform/web/publish/commit/59ddceb66f4bf9dc893cf68eb2be15464a53303c)
7
+ - 2026-03-04T15:42:22+08:00 [feat(chart): 数据标签加粗](http://lf.git.oa.mt/publish_platform/web/publish/commit/3ab4756a4fdea0979e56de01e5e9581bed568625)
8
+ - 2026-03-04T15:12:27+08:00 [feat(chart): 组合图颜色](http://lf.git.oa.mt/publish_platform/web/publish/commit/d448d5203de936018e95d8bcc301aaa877a64666)
9
+
10
+ **2.1.8** feat(chart): 柱状、折线、组合图的节点单独传递
11
+ - 2026-03-04T11:59:34+08:00 [feat(chart): 柱状、折线、组合图的节点单独传递](http://lf.git.oa.mt/publish_platform/web/publish/commit/5ef7b6c79b51438f7ae49edce74e060e5ffbd595)
12
+ - 2026-03-04T11:45:15+08:00 [fix(chart): 将node信息单独传递](http://lf.git.oa.mt/publish_platform/web/publish/commit/20b4209876bd464ff63674480eb3a308e7007a02)
13
+ - 2026-03-04T00:58:03+08:00 [fix(chart): 辅助线问题统一修复](http://lf.git.oa.mt/publish_platform/web/publish/commit/c40294f244ee7d8036ed1e92594b5e51980b55d0)
14
+ - 2026-03-04T00:18:41+08:00 [fix(chart): 辅助线scale统一设置为key:main](http://lf.git.oa.mt/publish_platform/web/publish/commit/67bf1b6913dd301aa3f1d840909e53bd6c6efcb2)
15
+ - 2026-03-03T23:26:48+08:00 [fix(chart): 组合图对比时间color设置修改](http://lf.git.oa.mt/publish_platform/web/publish/commit/3835d8c1ddc7937550daf45122f335f678e0730b)
16
+ - 2026-03-03T23:01:20+08:00 [fix(chart): inset边距去掉](http://lf.git.oa.mt/publish_platform/web/publish/commit/b96fec0d5939c9836caf5f8ceb51a988410d5e28)
17
+ - 2026-03-03T21:37:11+08:00 [feat(chart): 折线图图例根据indicators排序](http://lf.git.oa.mt/publish_platform/web/publish/commit/2d366548ba1aa170659f9c645f95045f4f510924)
18
+
1
19
  **2.1.7** fix(chart): 修复折线图有空数据的异常场景
2
20
  - 2026-03-03T17:50:03+08:00 [fix(chart): 修复折线图有空数据的异常场景](http://lf.git.oa.mt/publish_platform/web/publish/commit/3465ede843d4fb156932871cdf042315dbb17096)
3
21
  - 2026-03-03T17:38:27+08:00 [fix(chart): 组合图柱数据缺失问题优化](http://lf.git.oa.mt/publish_platform/web/publish/commit/fa55e35a7569b9e7000d2c4dc5d09eee3b60bfff)
@@ -50,6 +50,7 @@ const G2BarChart = ({ height = 300, data, x = "", y = "", indicatorMap, onChartC
50
50
  contextConfig.nodeMap
51
51
  ]);
52
52
  console.log("transformedData: bar final", transformedData);
53
+ const nodeData = transformedData.filter((item)=>item.nodeInfos?.info?.length > 0 || item.nodeInfos?.infosCompare?.length > 0);
53
54
  const maxY = useMemo(()=>{
54
55
  const values = transformedData.filter((item)=>"-" !== item[safeY] && void 0 !== item[safeY] && null !== item[safeY]).map((item)=>Number(item[safeY]) || 0);
55
56
  const dataMax = values.length > 0 ? Math.max(...values) : 0;
@@ -110,6 +111,7 @@ const G2BarChart = ({ height = 300, data, x = "", y = "", indicatorMap, onChartC
110
111
  }
111
112
  const chart = renderG2BarChart(containerRef.current, {
112
113
  data: filteredData,
114
+ nodeData,
113
115
  x,
114
116
  y: safeY,
115
117
  maxY,
@@ -149,7 +151,7 @@ const G2BarChart = ({ height = 300, data, x = "", y = "", indicatorMap, onChartC
149
151
  },
150
152
  auxiliaryLineData: auxiliaryLineData ?? [],
151
153
  onNodeListChange: (nodes)=>{
152
- console.log("g2bar node list:", nodes, nodes[0], nodes[1]);
154
+ console.log("g2bar node list:", nodes);
153
155
  setXYList(nodes);
154
156
  },
155
157
  timeRange,
@@ -11,6 +11,7 @@ import useG2TooltipContainer from "../shared/useG2TooltipContainer.js";
11
11
  import { getIndicatorCompareName } from "../../../utils/indicatorHelpers.js";
12
12
  import { renderG2CombineChart } from "./g2combine.js";
13
13
  import { G2BarLegend } from "./G2BarLegend.js";
14
+ import { sortByIndicators } from "./g2Helpers.js";
14
15
  const transformDataToGroupBarLineFormat = (data, x = "groupName", y = "", indicators)=>{
15
16
  if (!data || 0 === data.length) return [];
16
17
  return data.map((item)=>{
@@ -53,9 +54,9 @@ const transformDataToGroupBarLineFormat = (data, x = "groupName", y = "", indica
53
54
  }).flat();
54
55
  };
55
56
  const lineColors = [
56
- "#FE765E",
57
- "#945FB9",
58
- "#FF99C3"
57
+ '#FA8C16',
58
+ '#7CB305',
59
+ '#5CDBD3'
59
60
  ];
60
61
  const G2CombineChart = ({ height = 300, data, x = "", y = "", z = "", indicatorMap, onChartClick, legend = "", config, nodeSetting = {
61
62
  showType: 0,
@@ -109,6 +110,7 @@ const G2CombineChart = ({ height = 300, data, x = "", y = "", z = "", indicatorM
109
110
  isDescend
110
111
  ]);
111
112
  console.log("G2CombineChart transformedData:", transformedData, leftData, rightData);
113
+ const nodeData = transformedData.filter((item)=>item.nodeInfos?.info?.length > 0 || item.nodeInfos?.infosCompare?.length > 0);
112
114
  const { maxY } = useMemo(()=>{
113
115
  const key = isGroupRef.current ? "total" : safeY;
114
116
  const yValues = transformedData.filter((item)=>"-" !== item[key] && void 0 !== item[key] && null !== item[key]).map((item)=>Number(item[key]) || 0);
@@ -134,8 +136,9 @@ const G2CombineChart = ({ height = 300, data, x = "", y = "", z = "", indicatorM
134
136
  return;
135
137
  }
136
138
  const groupTypes = Array.from(new Set(transformedData.map((d)=>d.groupType.replace("_compare", "") + "_" + d.isCombine).filter((v)=>null != v)));
137
- const lineGroupTypeArr = groupTypes.filter((v)=>"true" === v.split("_")[1]);
138
- const items = groupTypes.map((id, index)=>{
139
+ const sortedGroupTypes = sortByIndicators(groupTypes, indicators);
140
+ const lineGroupTypeArr = sortedGroupTypes.filter((v)=>"true" === v.split("_")[1]);
141
+ const items = sortedGroupTypes.map((id, index)=>{
139
142
  const colorIndex = index;
140
143
  const indicatorId = id.split("_")[0];
141
144
  const isCombine = "true" === id.split("_")[1];
@@ -160,7 +163,8 @@ const G2CombineChart = ({ height = 300, data, x = "", y = "", z = "", indicatorM
160
163
  }, [
161
164
  transformedData,
162
165
  safeIndicatorMap,
163
- themeColors
166
+ themeColors,
167
+ indicators
164
168
  ]);
165
169
  const filterLeftData = useMemo(()=>{
166
170
  if (!activeIds.length) return leftData;
@@ -202,6 +206,7 @@ const G2CombineChart = ({ height = 300, data, x = "", y = "", z = "", indicatorM
202
206
  console.log("canvasMarginBottom:", canvasMarginBottom);
203
207
  const chart = renderG2CombineChart(containerRef.current, {
204
208
  data: filteredData,
209
+ nodeData,
205
210
  x,
206
211
  y: safeY,
207
212
  z,
@@ -7,6 +7,7 @@ import { DataAdapter } from "../../../adapters/DataAdapter.js";
7
7
  import { NodePopover } from "../../shared/NodePopover.js";
8
8
  import { NodeDetail } from "../../shared/NodeDetail.js";
9
9
  import { transformIndicatorList } from "../../../utils/dataTransform.js";
10
+ import { sortByIndicators } from "./g2Helpers.js";
10
11
  import G2CompareTooltip from "../shared/G2CompareTooltip.js";
11
12
  import useG2TooltipContainer from "../shared/useG2TooltipContainer.js";
12
13
  import { getIndicatorCompareName } from "../../../utils/indicatorHelpers.js";
@@ -52,6 +53,8 @@ const G2LineChart = ({ height = 300, data, x = "", y = "", z = "", indicatorMap,
52
53
  dataTransform,
53
54
  contextConfig.nodeMap
54
55
  ]);
56
+ const nodeData = transformedData.filter((item)=>item.nodeInfos?.info?.length > 0 || item.nodeInfos?.infosCompare?.length > 0);
57
+ console.log('nodeData:', nodeData);
55
58
  const { minY, maxY } = useMemo(()=>{
56
59
  const dataValues = transformedData.filter((item)=>"-" !== item[safeY] && void 0 !== item[safeY] && null !== item[safeY]).map((item)=>Number(item[safeY]));
57
60
  const compareValues = transformedData.filter((item)=>"-" !== item["subGroupValue"] && null != item["subGroupValue"]).map((item)=>Number(item["subGroupValue"]));
@@ -73,7 +76,6 @@ const G2LineChart = ({ height = 300, data, x = "", y = "", z = "", indicatorMap,
73
76
  safeY,
74
77
  auxiliaryLineData
75
78
  ]);
76
- console.log('minY, maxY:', minY, maxY);
77
79
  const formatAxis = useCallback((val)=>getAxisFormat(val, safeIndicatorMap, safeLegend), [
78
80
  safeIndicatorMap,
79
81
  safeLegend
@@ -85,7 +87,8 @@ const G2LineChart = ({ height = 300, data, x = "", y = "", z = "", indicatorMap,
85
87
  return;
86
88
  }
87
89
  const groupTypes = Array.from(new Set(transformedData.map((d)=>d.groupType).filter((v)=>null != v)));
88
- const items = groupTypes.map((id, index)=>{
90
+ const sortedGroupTypes = sortByIndicators(groupTypes, indicators);
91
+ const items = sortedGroupTypes.map((id, index)=>{
89
92
  const colorIndex = isCompare ? Math.floor(index / 2) : index;
90
93
  return {
91
94
  id: String(id),
@@ -106,7 +109,8 @@ const G2LineChart = ({ height = 300, data, x = "", y = "", z = "", indicatorMap,
106
109
  }, [
107
110
  transformedData,
108
111
  safeIndicatorMap,
109
- themeColors
112
+ themeColors,
113
+ indicators
110
114
  ]);
111
115
  const filteredData = useMemo(()=>{
112
116
  if (!activeIds.length) return transformedData;
@@ -125,6 +129,7 @@ const G2LineChart = ({ height = 300, data, x = "", y = "", z = "", indicatorMap,
125
129
  console.log("G2LineChart", x, y, minY, maxY);
126
130
  const chart = renderG2LineChart(containerRef.current, {
127
131
  data: filteredData,
132
+ nodeData,
128
133
  x,
129
134
  y: safeY,
130
135
  minY,
@@ -194,6 +194,7 @@ export declare function getMainView(chart: Chart): import("@antv/g2/lib/api/exte
194
194
  'composition.view': any;
195
195
  }>;
196
196
  export interface ScaleYLinearOptions {
197
+ key?: string;
197
198
  field?: string;
198
199
  domainMin?: number;
199
200
  domainMax?: number;
@@ -296,4 +297,13 @@ export interface GetColorByGroupTypeOptions {
296
297
  */
297
298
  export declare function getColorByGroupType(groupType: string, options: GetColorByGroupTypeOptions): string;
298
299
  export declare function applyHighlightDate(view: any, x: string, data: any, highlightDate: string[], isHighlight: boolean): void;
300
+ export declare function applyNodeData(view: any, nodeData: any[], x: string, y: string): {
301
+ pointP: {
302
+ x: number;
303
+ y: number;
304
+ };
305
+ pointData: any;
306
+ color: string;
307
+ }[];
299
308
  export declare function adjustDomainMax(domainMin: number, domainMax: number): number;
309
+ export declare const sortByIndicators: (arr: string[], indicators: string[]) => string[];
@@ -14,7 +14,7 @@ function getMainView(chart) {
14
14
  return layer.view();
15
15
  }
16
16
  function applyScaleYLinear(view, options = {}) {
17
- const { field = 'y', domainMin = 0, domainMax, nice = true, clamp = true, tickCount = 5, minLimit, maxLimit, tickMethod } = options;
17
+ const { field = 'y', domainMin = 0, domainMax, nice = true, clamp = true, tickCount = 5, minLimit, maxLimit, tickMethod, key } = options;
18
18
  view.scale({
19
19
  [field]: {
20
20
  type: 'linear',
@@ -25,6 +25,7 @@ function applyScaleYLinear(view, options = {}) {
25
25
  clamp,
26
26
  nice,
27
27
  tickCount,
28
+ key,
28
29
  ...null != minLimit && {
29
30
  minLimit
30
31
  },
@@ -148,18 +149,19 @@ function applyAuxiliaryLineY(view, lines, options = {}) {
148
149
  console.log('applyAuxiliaryLineY:', lines);
149
150
  const { stroke = '#F4664A', strokeOpacity = 1, labelMaxLength = 5 } = options;
150
151
  lines.forEach((auxLine)=>{
151
- view.lineY().encode('y', auxLine.value).style('stroke', stroke).style('strokeOpacity', strokeOpacity).style('lineWidth', 1).style('shadowColor', 'transparent').axis('y', {
152
- title: false,
153
- grid: false,
154
- label: false,
155
- tick: false
156
- }).label({
152
+ console.log('lines:', auxLine);
153
+ view.lineY().encode('y', auxLine.value).style('stroke', stroke).style('strokeOpacity', strokeOpacity).style('lineWidth', 1).style('shadowColor', 'transparent').scale('y', {
154
+ key: auxLine?.axis === 'right' ? 'line' : 'main'
155
+ }).axis('x', false).label({
157
156
  dx: 0,
158
- dy: -5,
159
- text: splitTextToMultiline(auxLine.name, labelMaxLength, '<br />'),
157
+ dy: 0,
158
+ text: splitTextToMultiline(auxLine.name, labelMaxLength, '\n'),
160
159
  position: auxLine?.axis === 'right' ? 'bottom-right' : 'bottom-left',
161
- style: {},
162
- render: (text)=>`<div style="background-color: transparent; padding: 5px; border-radius: 5px;font-size: 12px;position: absolute;left: -4px; top: -24px; width: 100px;color: ${stroke}; font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif;">${text}</div>`
160
+ style: {
161
+ fill: stroke,
162
+ shadowColor: 'transparent',
163
+ fillOpacity: 1
164
+ }
163
165
  });
164
166
  });
165
167
  }
@@ -183,7 +185,7 @@ function applyHighlightDate(view, x, data, highlightDate, isHighlight) {
183
185
  domainMax: 100,
184
186
  independent: true
185
187
  }).tooltip(false).axis('y', {
186
- position: 'right',
188
+ position: 'top',
187
189
  title: false,
188
190
  grid: false,
189
191
  label: false,
@@ -200,16 +202,75 @@ function applyHighlightDate(view, x, data, highlightDate, isHighlight) {
200
202
  domainMax: 100,
201
203
  independent: true
202
204
  }).tooltip(true).axis('y', {
205
+ position: 'top',
203
206
  title: false,
204
207
  grid: false,
205
208
  label: false,
206
209
  tick: false
207
210
  }).style({
208
211
  stroke: 'transparent',
209
- strokeOpacity: 0
212
+ strokeOpacity: 1
210
213
  });
211
214
  }
215
+ function applyNodeData(view, nodeData, x, y) {
216
+ const nodeList = [];
217
+ nodeData?.forEach((item)=>{
218
+ view.shape().data([
219
+ {
220
+ [x]: item[x],
221
+ [y]: 0
222
+ }
223
+ ]).encode('x', x).encode('y', y).tooltip(false).scale('y', {
224
+ key: 'main'
225
+ }).style({
226
+ render: ({ x: px, y: py }, context)=>{
227
+ const { document } = context;
228
+ const g = document.createElement('g', {});
229
+ const { paddingLeft = 24, marginLeft = 12 } = context?.coordinate?.options || {};
230
+ const adjustLeft = paddingLeft + marginLeft;
231
+ if (item.nodeInfos?.info?.length > 0 || item.nodeInfos?.infosCompare?.length > 0) {
232
+ nodeList.push({
233
+ pointP: {
234
+ x: px + adjustLeft,
235
+ y: py
236
+ },
237
+ pointData: item.nodeInfos || {},
238
+ color: item.color
239
+ });
240
+ const c1 = document.createElement('circle', {
241
+ style: {
242
+ cx: px,
243
+ cy: py,
244
+ r: 2,
245
+ fill: 'white'
246
+ }
247
+ });
248
+ const c2 = document.createElement('circle', {
249
+ style: {
250
+ cx: px,
251
+ cy: py,
252
+ r: 5,
253
+ fill: item.color
254
+ }
255
+ });
256
+ g.appendChild(c2);
257
+ g.appendChild(c1);
258
+ }
259
+ return g;
260
+ }
261
+ });
262
+ });
263
+ return nodeList;
264
+ }
212
265
  function adjustDomainMax(domainMin, domainMax) {
213
266
  return domainMax === domainMin ? domainMin > 0 ? 1.1 * domainMax : domainMax + 1 : domainMax;
214
267
  }
215
- export { adjustDomainMax, applyAuxiliaryLineY, applyAxisX, applyAxisY, applyHighlightDate, applyLegendColor, applyScaleYLinear, createChart, getColorByGroupType, getMainView };
268
+ const sortByIndicators = (arr, indicators)=>arr.sort((a, b)=>{
269
+ const baseA = a.split('_')[0];
270
+ const baseB = b.split('_')[0];
271
+ const indexA = indicators.indexOf(baseA);
272
+ const indexB = indicators.indexOf(baseB);
273
+ if (-1 !== indexA && -1 !== indexB) return indexA - indexB;
274
+ return 0;
275
+ });
276
+ export { adjustDomainMax, applyAuxiliaryLineY, applyAxisX, applyAxisY, applyHighlightDate, applyLegendColor, applyNodeData, applyScaleYLinear, createChart, getColorByGroupType, getMainView, sortByIndicators };
@@ -3,6 +3,8 @@ import type { ChartTimeRange } from '../../../core/ChartTypes';
3
3
  export interface RenderG2BarChartOptions {
4
4
  /** 已转换后的数据:约定包含 groupName、groupType、groupValue 等字段 */
5
5
  data: any[];
6
+ /** 节点数据 */
7
+ nodeData: any[];
6
8
  /** X 轴字段,如 groupName */
7
9
  x: string;
8
10
  /** Y 轴字段,如 groupValue / cost */
@@ -1,8 +1,10 @@
1
1
  import { lines } from "@antv/g-pattern";
2
- import { applyAuxiliaryLineY, applyAxisX, applyAxisY, applyHighlightDate, applyScaleYLinear, createChart, getColorByGroupType, getMainView } from "./g2Helpers.js";
2
+ import { applyAuxiliaryLineY, applyAxisX, applyAxisY, applyHighlightDate, applyNodeData, applyScaleYLinear, createChart, getColorByGroupType, getMainView } from "./g2Helpers.js";
3
3
  const Y_AXIS_FIELD = 'groupValue';
4
+ const CLOSE_NODE_DEBUG = false;
5
+ const CLOSE_HIGHLIGHT_DEBUG = false;
4
6
  function renderG2BarChart(container, options) {
5
- const { data, x, y, maxY, timeRange: _timeRange, themeColors, indicators = [], indicatorMap: _indicatorMap = {}, formatAxis, highlightDate = [], isDataTag = false, isLegend = true, isHorizontal = false, isHighlight = true, isCompare = false, isClickable = false, legend, formatLabel, height = 300, tooltipRender, auxiliaryLineData = [], onNodeListChange, onChartRender } = options;
7
+ const { data, nodeData, x, y, maxY, timeRange: _timeRange, themeColors, indicators = [], indicatorMap: _indicatorMap = {}, formatAxis, highlightDate = [], isDataTag = false, isLegend = true, isHorizontal = false, isHighlight = true, isCompare = false, isClickable = false, legend, formatLabel, height = 300, tooltipRender, auxiliaryLineData = [], onNodeListChange, onChartRender } = options;
6
8
  const colorOpts = {
7
9
  themeColors,
8
10
  primaryKey: y,
@@ -30,13 +32,11 @@ function renderG2BarChart(container, options) {
30
32
  });
31
33
  view.data(data);
32
34
  applyScaleYLinear(view, {
33
- field: 'y',
34
35
  domainMin: 0,
35
36
  domainMax: maxY,
36
- nice: true,
37
- clamp: true
37
+ key: 'main'
38
38
  });
39
- applyHighlightDate(view, x, data, highlightDate, isHighlight);
39
+ if (!CLOSE_HIGHLIGHT_DEBUG) applyHighlightDate(view, x, data, highlightDate, isHighlight);
40
40
  console.log('g2bar data:', data, y);
41
41
  const interval = view.interval().encode('x', x).encode('y', y).encode('color', 'groupType').transform({
42
42
  type: 'dodgeX',
@@ -145,53 +145,15 @@ function renderG2BarChart(container, options) {
145
145
  bounding: tooltipBounding
146
146
  });
147
147
  applyAuxiliaryLineY(view, auxiliaryLineData);
148
- const nodeList = [];
149
148
  console.log('nodeList data:', data);
150
- data.forEach((item)=>{
151
- view.shape().data([
152
- {
153
- [x]: item[x],
154
- [y]: 0
155
- }
156
- ]).encode('x', x).encode('y', y).tooltip(false).style({
157
- render: ({ x: px, y: py }, context)=>{
158
- const { document } = context;
159
- const g = document.createElement('g', {});
160
- const { paddingLeft = 24, marginLeft = 12 } = context?.coordinate?.options || {};
161
- const adjustLeft = paddingLeft + marginLeft;
162
- if (item.nodeInfos?.info?.length > 0 || item.nodeInfos?.infosCompare?.length > 0) {
163
- nodeList.push({
164
- pointP: {
165
- x: px + adjustLeft,
166
- y: py
167
- },
168
- pointData: item.nodeInfos || {},
169
- color: item.color
170
- });
171
- const c1 = document.createElement('circle', {
172
- style: {
173
- cx: px,
174
- cy: py,
175
- r: 2,
176
- fill: 'white'
177
- }
178
- });
179
- const c2 = document.createElement('circle', {
180
- style: {
181
- cx: px,
182
- cy: py,
183
- r: 5,
184
- fill: item.color
185
- }
186
- });
187
- g.appendChild(c2);
188
- g.appendChild(c1);
189
- }
190
- return g;
191
- }
192
- });
193
- });
149
+ if (!CLOSE_NODE_DEBUG) {
150
+ const nodeList = applyNodeData(view, nodeData, x, y);
151
+ onNodeListChange?.(nodeList);
152
+ }
194
153
  if (isDataTag && formatLabel) interval.label({
154
+ style: {
155
+ fontWeight: 600
156
+ },
195
157
  text: (d)=>formatLabel(d),
196
158
  position: isHorizontal ? 'right' : 'top',
197
159
  offset: 0,
@@ -208,7 +170,6 @@ function renderG2BarChart(container, options) {
208
170
  let hasEmittedNodeList = false;
209
171
  chart.on('afterrender', (_e)=>{
210
172
  if (hasEmittedNodeList) return;
211
- if (onNodeListChange) onNodeListChange(nodeList);
212
173
  console.log('chart.coordinateBBox:', chart.getContext(), view.getCoordinate());
213
174
  const views = chart.getContext()?.views;
214
175
  const viewCoordinate = views?.[0]?.layout;
@@ -8,6 +8,8 @@ import { type AuxiliaryLineItem } from "./g2Helpers";
8
8
  export interface RenderG2CombineChartOptions {
9
9
  /** 已转换后的数据:约定包含 groupName、groupType、groupValue 等字段 */
10
10
  data: any[];
11
+ /** 节点数据 */
12
+ nodeData: any[];
11
13
  /** X 轴字段,如 groupName */
12
14
  x: string;
13
15
  /** 柱状图 Y 字段,如 groupValue 或某指标字段 */
@@ -1,11 +1,11 @@
1
1
  import { lines } from "@antv/g-pattern";
2
- import { applyAuxiliaryLineY, applyAxisX, applyHighlightDate, createChart, getMainView } from "./g2Helpers.js";
2
+ import { applyAuxiliaryLineY, applyAxisX, applyHighlightDate, applyNodeData, applyScaleYLinear, createChart, getMainView } from "./g2Helpers.js";
3
3
  import { getIndicatorCompareName } from "../../../utils/indicatorHelpers.js";
4
4
  const Y_AXIS_FIELD = 'groupValue';
5
5
  const BAR_Y_FIELD = 'barValue';
6
6
  const LINE_Y_FIELD = 'lineValue';
7
7
  function renderG2CombineChart(container, options) {
8
- const { data, x, y, z: _z, maxY, themeColors, indicatorMap: _indicatorMap, formatAxis, formatLineAxis, isDataTag = true, isCombineDataTag = true, isLegend: _isLegend = false, isCompare = false, formatLabel, highlightDate = [], height = 300, isHighlight = true, isClickable = false, indicators = [], tooltipRender, auxiliaryLineData = [], onNodeListChange, lineColors, onChartRender, isGroup, legendItems = [], indicatorId } = options;
8
+ const { data, nodeData, x, y, z: _z, maxY, themeColors, indicatorMap: _indicatorMap, formatAxis, formatLineAxis, isDataTag = true, isCombineDataTag = true, isLegend: _isLegend = false, isCompare = false, formatLabel, highlightDate = [], height = 300, isHighlight = true, isClickable = false, indicators = [], tooltipRender, auxiliaryLineData = [], onNodeListChange, lineColors, onChartRender, isGroup, legendItems = [], indicatorId } = options;
9
9
  const chart = createChart({
10
10
  container,
11
11
  height,
@@ -52,14 +52,15 @@ function renderG2CombineChart(container, options) {
52
52
  }).style({
53
53
  columnWidthRatio: 0.6,
54
54
  insetLeft: (_d, index, _data, _column)=>{
55
+ console.log('insetLeft:', index, isCompare);
55
56
  if (isGroup) return 0;
56
- if (isCompare) return index % 2 === 0 ? 4 : 0;
57
- return 4;
57
+ if (isCompare) return index % 2 === 0 ? 0 : 0;
58
+ return 0;
58
59
  },
59
60
  insetRight: (_d, index, _data, _column)=>{
60
61
  if (isGroup) return 0;
61
- if (isCompare) return index % 2 === 1 ? 4 : 0;
62
- return 4;
62
+ if (isCompare) return index % 2 === 1 ? 0 : 0;
63
+ return 0;
63
64
  },
64
65
  fill: (datum)=>{
65
66
  const groupType = String(datum.groupType ?? '');
@@ -81,17 +82,15 @@ function renderG2CombineChart(container, options) {
81
82
  cursor: isClickable ? 'pointer' : 'default',
82
83
  stroke: 'transparent'
83
84
  });
84
- interval.scale('y', {
85
- type: 'linear',
85
+ const chartScale = {
86
86
  domainMin: 0,
87
87
  domainMax: finalIntervalMax,
88
- nice: true,
89
- clamp: true,
90
- key: 'bar',
88
+ key: 'main',
91
89
  tickMethod: (min, max)=>Array.from({
92
90
  length: 6
93
91
  }, (_, i)=>min + (max - min) * i / 5)
94
- });
92
+ };
93
+ applyScaleYLinear(interval, chartScale);
95
94
  interval.axis('y', {
96
95
  position: 'left',
97
96
  title: false,
@@ -129,7 +128,8 @@ function renderG2CombineChart(container, options) {
129
128
  indicatorId: datum['groupType'],
130
129
  channel: Y_AXIS_FIELD,
131
130
  color: barColor || 'transparent',
132
- isCombine: false
131
+ isCombine: false,
132
+ x: datum[x]
133
133
  },
134
134
  isCompare ? (datum)=>datum.groupType.includes('_compare') ? {
135
135
  value: datum[BAR_Y_FIELD],
@@ -150,12 +150,12 @@ function renderG2CombineChart(container, options) {
150
150
  } : false : false
151
151
  ].filter(Boolean)
152
152
  });
153
- const lineData = data.filter((item)=>item.isCombine && !item.groupType.includes('_compare')).map((item)=>({
153
+ const lineData = data.filter((item)=>item.isCombine && !item.groupType.includes('_compare')).filter((item)=>'' !== item[Y_AXIS_FIELD]).map((item)=>({
154
154
  ...item,
155
155
  [LINE_Y_FIELD]: item[Y_AXIS_FIELD]
156
156
  }));
157
157
  console.log('renderG2CombineChart: line data:', lineData);
158
- const compareLineData = data.filter((item)=>item.isCombine && item.groupType.includes('_compare')).map((item)=>({
158
+ const compareLineData = data.filter((item)=>item.isCombine && item.groupType.includes('_compare')).filter((item)=>'' !== item[Y_AXIS_FIELD]).map((item)=>({
159
159
  ...item,
160
160
  [LINE_Y_FIELD]: item[Y_AXIS_FIELD]
161
161
  }));
@@ -164,53 +164,41 @@ function renderG2CombineChart(container, options) {
164
164
  const compareLineMaxY = compareLineData.reduce((max, item)=>Math.max(max, item[LINE_Y_FIELD]), 0);
165
165
  const lineFinalMaxY = Math.max(lineMaxY, compareLineMaxY) || 1;
166
166
  const finalLineMax = Math.max(lineFinalMaxY, maxAux);
167
+ console.log('lineData:', lineData);
167
168
  const line = view.line().data(lineData).encode("x", x).encode("y", LINE_Y_FIELD).encode('color', 'groupType').style({
168
169
  lineWidth: 2,
169
170
  stroke: (datum)=>{
170
- const groupTypeSet = new Set(lineData.map((item)=>item.groupType));
171
- const groupTypeArr = [
172
- ...groupTypeSet
173
- ];
174
- const groupType = String(datum[0]?.groupType ?? '');
175
- const index = groupTypeArr.findIndex((item)=>item === groupType);
176
- const color = lineColors[index] || lineColors[0];
177
- return color;
171
+ const currentDatum = datum[0];
172
+ const item = legendItems.find((item)=>item.id === `${currentDatum?.groupType}_${currentDatum?.isCombine}`);
173
+ return item?.color || lineColors[0];
178
174
  }
179
175
  });
180
176
  line.tooltip({
181
177
  items: [
182
178
  (datum)=>{
183
- const groupTypeSet = new Set(lineData.map((item)=>item.groupType));
184
- const groupTypeArr = [
185
- ...groupTypeSet
186
- ];
187
- const groupType = String(datum?.groupType ?? '');
188
- const index = groupTypeArr.findIndex((item)=>item === groupType);
189
- console.log('line: groupTypeArr:', groupTypeArr, groupType, index, lineColors, getIndicatorCompareName(_indicatorMap, datum['groupType']), datum['groupType']);
179
+ const item = legendItems.find((item)=>item.id === `${datum?.groupType}_${datum?.isCombine}`);
190
180
  return {
191
181
  value: datum[LINE_Y_FIELD],
192
182
  name: getIndicatorCompareName(_indicatorMap, datum['groupType']),
193
183
  indicatorId: datum['groupType'],
194
184
  channel: Y_AXIS_FIELD,
195
- color: lineColors[index] || lineColors[0],
185
+ color: item?.color || lineColors[0],
196
186
  isCombine: true,
197
- tipType: 'line'
187
+ tipType: 'line',
188
+ x: datum[x]
198
189
  };
199
190
  }
200
191
  ]
201
192
  });
202
- line.scale('y', {
203
- type: 'linear',
193
+ const chartSideScale = {
204
194
  domainMin: 0,
205
195
  domainMax: finalLineMax,
206
- nice: true,
207
- clamp: true,
208
196
  key: 'line',
209
- independent: true,
210
197
  tickMethod: (min, max)=>Array.from({
211
198
  length: 6
212
199
  }, (_, i)=>min + (max - min) * i / 5)
213
- });
200
+ };
201
+ applyScaleYLinear(line, chartSideScale);
214
202
  line.axis('y', {
215
203
  position: 'right',
216
204
  title: false,
@@ -262,16 +250,18 @@ function renderG2CombineChart(container, options) {
262
250
  channel: Y_AXIS_FIELD,
263
251
  color: lineColors[indicators.slice(1).indexOf(String(datum['groupType'])) ?? 0] || 'transparent',
264
252
  isCombine: true,
265
- tipType: 'compareline'
253
+ tipType: 'compareline',
254
+ x: datum[x]
266
255
  } : false,
267
256
  (datum)=>datum.groupType.includes('_compare') ? {
268
257
  name: datum['groupType'].replace('_compare', '_change'),
269
258
  indicatorId: datum['groupType'].replace('_compare', ''),
270
- color: 'blue',
259
+ color: 'transparent',
271
260
  value: datum?.change,
272
261
  isChange: true,
273
262
  isCombine: true,
274
- tipType: 'compareline'
263
+ tipType: 'compareline',
264
+ x: datum[x]
275
265
  } : false
276
266
  ].filter(Boolean)
277
267
  });
@@ -281,14 +271,30 @@ function renderG2CombineChart(container, options) {
281
271
  marker: false,
282
272
  render: (event, payload)=>{
283
273
  const { title, items } = payload;
274
+ console.log('tooltipRender:', title, items);
275
+ let safeTitle = title.replace(/,.*$/, '');
284
276
  const baseItems = items.filter((item)=>!item.isCombine);
277
+ const safeItems = baseItems.map((item)=>{
278
+ if (item.x !== safeTitle) return {
279
+ ...item,
280
+ value: '-'
281
+ };
282
+ return item;
283
+ });
285
284
  const combineItems = items.filter((item)=>item.isCombine);
285
+ const safeCombineItems = combineItems.map((item)=>{
286
+ if (item.x !== safeTitle) return {
287
+ ...item,
288
+ value: '-'
289
+ };
290
+ return item;
291
+ });
286
292
  const indicatorOrder = new Map(indicators.map((id, i)=>[
287
293
  id,
288
294
  i
289
295
  ]));
290
296
  const sortedCombineItems = [
291
- ...combineItems
297
+ ...safeCombineItems
292
298
  ].sort((a, b)=>{
293
299
  const orderA = indicatorOrder.get(a.indicatorId) ?? 1 / 0;
294
300
  const orderB = indicatorOrder.get(b.indicatorId) ?? 1 / 0;
@@ -300,8 +306,8 @@ function renderG2CombineChart(container, options) {
300
306
  };
301
307
  return typeRank(a) - typeRank(b);
302
308
  });
303
- const content = tooltipRender(title, [
304
- ...baseItems,
309
+ const content = tooltipRender(safeTitle, [
310
+ ...safeItems,
305
311
  ...sortedCombineItems
306
312
  ]) ?? null;
307
313
  if (content) {
@@ -361,68 +367,8 @@ function renderG2CombineChart(container, options) {
361
367
  tipBoxShadow: '0 3px 6px -4px rgba(0, 0, 0, 1)'
362
368
  });
363
369
  applyAuxiliaryLineY(view, auxiliaryLineData);
364
- const nodeList = [];
365
- console.log('nodeList data:', data);
366
- data.forEach((item)=>{
367
- view.shape().data([
368
- {
369
- [x]: item[x],
370
- [y]: 0
371
- }
372
- ]).encode('x', x).encode('y', y).tooltip(false).scale('y', {
373
- key: 'node',
374
- domainMin: 0,
375
- domainMax: 1,
376
- nice: true,
377
- clamp: true
378
- }).axis('y', {
379
- grid: false,
380
- title: false,
381
- tick: false,
382
- label: false,
383
- gridStrokeOpacity: 1,
384
- gridLineDash: [
385
- 0,
386
- 0
387
- ]
388
- }).style({
389
- render: ({ x: px, y: py }, context)=>{
390
- const { document } = context;
391
- const g = document.createElement('g', {});
392
- const { paddingLeft = 24, marginLeft = 12 } = context?.coordinate?.options || {};
393
- const adjustLeft = paddingLeft + marginLeft;
394
- if (item.nodeInfos?.info?.length > 0 || item.nodeInfos?.infosCompare?.length > 0) {
395
- nodeList.push({
396
- pointP: {
397
- x: px + adjustLeft,
398
- y: py
399
- },
400
- pointData: item.nodeInfos || {},
401
- color: item.color
402
- });
403
- const c1 = document.createElement('circle', {
404
- style: {
405
- cx: px,
406
- cy: py,
407
- r: 2,
408
- fill: 'white'
409
- }
410
- });
411
- const c2 = document.createElement('circle', {
412
- style: {
413
- cx: px,
414
- cy: py,
415
- r: 5,
416
- fill: item.color
417
- }
418
- });
419
- g.appendChild(c2);
420
- g.appendChild(c1);
421
- }
422
- return g;
423
- }
424
- });
425
- });
370
+ const nodeList = applyNodeData(view, nodeData, x, 'groupValue');
371
+ onNodeListChange?.(nodeList);
426
372
  if (formatLabel) {
427
373
  if (isDataTag) {
428
374
  const groupedByX = intervalData.reduce((acc, item)=>{
@@ -440,6 +386,9 @@ function renderG2CombineChart(container, options) {
440
386
  dy: -16,
441
387
  dx: -10,
442
388
  offset: 0,
389
+ style: {
390
+ fontWeight: 600
391
+ },
443
392
  text: (d)=>{
444
393
  if (!isGroup) return formatLabel(d);
445
394
  if (lastItemsInEachStack.has(d)) return formatLabel(d);
@@ -451,6 +400,9 @@ function renderG2CombineChart(container, options) {
451
400
  dy: -10,
452
401
  dx: 10,
453
402
  offset: 0,
403
+ style: {
404
+ fontWeight: 600
405
+ },
454
406
  text: (d)=>formatLabel(d)
455
407
  });
456
408
  view.labelTransform([
@@ -7,6 +7,8 @@ import { ChartTimeRange } from '../../../core/ChartTypes';
7
7
  export interface RenderG2LineChartOptions {
8
8
  /** 已转换后的数据(含 groupValue,groupType 可能带 _compare) */
9
9
  data: any[];
10
+ /** 节点数据 */
11
+ nodeData: any[];
10
12
  /** X 轴字段,如 groupName */
11
13
  x: string;
12
14
  /** 主指标 key,用于取色与图例 */
@@ -1,7 +1,7 @@
1
- import { applyAuxiliaryLineY, applyAxisX, applyAxisY, applyHighlightDate, applyScaleYLinear, createChart, getColorByGroupType, getMainView } from "./g2Helpers.js";
1
+ import { applyAuxiliaryLineY, applyAxisX, applyAxisY, applyHighlightDate, applyNodeData, applyScaleYLinear, createChart, getColorByGroupType, getMainView } from "./g2Helpers.js";
2
2
  const Y_AXIS_FIELD = 'groupValue';
3
3
  function renderG2LineChart(container, options) {
4
- const { data, x, y, minY, maxY, timeRange: _timeRange, themeColors, indicators = [], indicatorMap: _indicatorMap = {}, formatAxis, highlightDate = [], auxiliaryLineData = [], isDataTag = false, isLegend = true, isHighlight = true, formatLabel, height = 300, legendLength: _legendLength, legendSize: _legendSize, tooltipRender, onNodeListChange, onChartRender } = options;
4
+ const { data, nodeData, x, y, minY, maxY, timeRange: _timeRange, themeColors, indicators = [], indicatorMap: _indicatorMap = {}, formatAxis, highlightDate = [], auxiliaryLineData = [], isDataTag = false, isLegend = true, isHighlight = true, formatLabel, height = 300, legendLength: _legendLength, legendSize: _legendSize, tooltipRender, onNodeListChange, onChartRender } = options;
5
5
  console.log('g2line data:', data, x, y);
6
6
  const colorOpts = {
7
7
  themeColors,
@@ -23,11 +23,9 @@ function renderG2LineChart(container, options) {
23
23
  view.data(data);
24
24
  const domainMin = minY ?? 0;
25
25
  applyScaleYLinear(view, {
26
- field: 'y',
27
26
  domainMin,
28
27
  domainMax: maxY,
29
- nice: true,
30
- clamp: true
28
+ key: 'main'
31
29
  });
32
30
  applyHighlightDate(view, x, data, highlightDate, isHighlight);
33
31
  console.log('g2linets:', x, Y_AXIS_FIELD, data, indicators);
@@ -80,7 +78,8 @@ function renderG2LineChart(container, options) {
80
78
  indicatorId: datum['groupType'].replace('_compare', ''),
81
79
  value: datum?.change,
82
80
  isChange: true,
83
- color: 'transparent'
81
+ color: 'transparent',
82
+ hidden: indicators?.length > 1
84
83
  })
85
84
  ]
86
85
  });
@@ -133,63 +132,25 @@ function renderG2LineChart(container, options) {
133
132
  tipBoxShadow: '0 3px 6px -4px rgba(0, 0, 0, 1)'
134
133
  });
135
134
  applyAuxiliaryLineY(view, auxiliaryLineData);
136
- const nodeList = [];
137
- console.log('nodeList data:', data);
138
- data.forEach((item)=>{
139
- view.shape().data([
140
- {
141
- [x]: item[x],
142
- [y]: 0
143
- }
144
- ]).encode('x', x).encode('y', y).tooltip(false).style({
145
- render: ({ x: px, y: py }, context)=>{
146
- const { document } = context;
147
- const g = document.createElement('g', {});
148
- const { paddingLeft = 24, marginLeft = 12 } = context?.coordinate?.options || {};
149
- const adjustLeft = paddingLeft + marginLeft;
150
- if (item.nodeInfos?.info?.length > 0 || item.nodeInfos?.infosCompare?.length > 0) {
151
- nodeList.push({
152
- pointP: {
153
- x: px + adjustLeft,
154
- y: py
155
- },
156
- pointData: item.nodeInfos || {},
157
- color: item.color
158
- });
159
- const c1 = document.createElement('circle', {
160
- style: {
161
- cx: px,
162
- cy: py,
163
- r: 2,
164
- fill: 'white'
165
- }
166
- });
167
- const c2 = document.createElement('circle', {
168
- style: {
169
- cx: px,
170
- cy: py,
171
- r: 5,
172
- fill: item.color
173
- }
174
- });
175
- g.appendChild(c2);
176
- g.appendChild(c1);
177
- }
178
- return g;
179
- }
180
- });
181
- });
135
+ const nodeList = applyNodeData(view, nodeData, x, y);
136
+ onNodeListChange?.(nodeList);
182
137
  if (isDataTag && formatLabel) {
183
138
  line.label({
184
139
  dy: -10,
185
140
  dx: -10,
186
141
  offset: 0,
142
+ style: {
143
+ fontWeight: 600
144
+ },
187
145
  text: (d)=>formatLabel(d)
188
146
  });
189
147
  compareLine.label({
190
148
  dy: -10,
191
149
  dx: -10,
192
150
  offset: 0,
151
+ style: {
152
+ fontWeight: 600
153
+ },
193
154
  text: (d)=>formatLabel(d)
194
155
  });
195
156
  view.labelTransform([
@@ -6,6 +6,7 @@ type Item = {
6
6
  compareTime?: undefined | string;
7
7
  indicatorId?: string;
8
8
  percent?: string | number;
9
+ hidden?: boolean;
9
10
  };
10
11
  interface Props {
11
12
  isGroupBar?: boolean;
@@ -4,6 +4,7 @@ import { CompareChange } from "@publishfx/publish-components";
4
4
  import { getIndicatorCompareName } from "../../../utils/indicatorHelpers.js";
5
5
  const G2CompareTooltip = ({ isGroupBar = false, title, items, safeIndicatorMap, formatter, safeLegend, auxiliaryLineData })=>{
6
6
  let auxiIndicatorId = "";
7
+ console.log('G2CompareTooltip:', items);
7
8
  const uniqueColors = [];
8
9
  return /*#__PURE__*/ jsxs("div", {
9
10
  style: {
@@ -13,14 +14,14 @@ const G2CompareTooltip = ({ isGroupBar = false, title, items, safeIndicatorMap,
13
14
  /*#__PURE__*/ jsx("div", {
14
15
  children: title
15
16
  }),
16
- items?.map(({ color, value, isChange, compareTime, indicatorId, name, percent }, index)=>{
17
+ items?.map(({ color, value, isChange, compareTime, indicatorId, name, percent, hidden }, index)=>{
17
18
  let isFirst = false;
18
19
  if (0 === index) auxiIndicatorId = indicatorId ?? "";
19
20
  if (color && !uniqueColors.includes(color)) {
20
21
  isFirst = true;
21
22
  uniqueColors.push(color);
22
23
  }
23
- return /*#__PURE__*/ jsxs("div", {
24
+ return !hidden && /*#__PURE__*/ jsxs("div", {
24
25
  style: {
25
26
  display: "flex",
26
27
  justifyContent: "space-between",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@publishfx/publish-chart",
3
- "version": "2.1.7",
3
+ "version": "2.1.9",
4
4
  "description": "A React chart component library for the Publish platform, including BarChart, LineChart, BarLineChart and other visualization components",
5
5
  "type": "module",
6
6
  "keywords": [