@publishfx/publish-chart 2.1.3 → 2.1.5

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,19 @@
1
+ **2.1.5** fix(chart): 修正ts错误
2
+ - 2026-03-03T04:41:18+08:00 [fix(chart): 修正ts错误](http://lf.git.oa.mt/publish_platform/web/publish/commit/ed6bc3403d6c06d8c0cce6f0193a447d74b68a3a)
3
+ - 2026-03-03T04:38:12+08:00 [fix(chart): 组合图代码整理](http://lf.git.oa.mt/publish_platform/web/publish/commit/6a94afb106447e54143f4a29e7d8fa24c718b321)
4
+ - 2026-03-03T01:44:41+08:00 [fix(chart): 修复一些问题](http://lf.git.oa.mt/publish_platform/web/publish/commit/52b05bffc199010d0ed76c112f615937c33edc53)
5
+ - 2026-03-03T00:19:14+08:00 [fix(chart): 辅助线不显示y轴](http://lf.git.oa.mt/publish_platform/web/publish/commit/4a7de7122d0ec4f037b95927f93a2626e7a8837a)
6
+ - 2026-03-03T00:13:56+08:00 [fix: 修复一批组合图和折线图的BUG](http://lf.git.oa.mt/publish_platform/web/publish/commit/c9f3f2a758ae49c94dada96acb859e8e842877ea)
7
+ - 2026-03-02T21:49:02+08:00 [feat(chart): 组合图排序](http://lf.git.oa.mt/publish_platform/web/publish/commit/46000898aac62b20b9c4f1543a0437808e795021)
8
+ - 2026-03-02T20:35:15+08:00 [fix: [f-6849783906] 修复柱状图倒序问题及图例编辑时不展示问题](http://lf.git.oa.mt/publish_platform/web/publish/commit/5fc94ba48503403c2aee24d59fc9ad6e71ce3a2d)
9
+ - 2026-03-02T20:24:49+08:00 [feat(chart): 组合图数据标签](http://lf.git.oa.mt/publish_platform/web/publish/commit/ec86c8ef7479f60c19d9a817212b2b3290a9c00f)
10
+ - 2026-03-02T19:37:12+08:00 [feat: 组合图辅助线](http://lf.git.oa.mt/publish_platform/web/publish/commit/7ea103172eb0f2529bd067a4187c4f9d6387dd0f)
11
+ - 2026-03-02T19:06:57+08:00 [feat(chart): 组合图折线逻辑](http://lf.git.oa.mt/publish_platform/web/publish/commit/c13e0dbf072b4736742a84890394a923495a6c54)
12
+
13
+ **2.1.4** feat(chart): 柱状、折线、组合三个图表支持onChartClick
14
+ - 2026-03-02T15:27:33+08:00 [feat(chart): 柱状、折线、组合三个图表支持onChartClick](http://lf.git.oa.mt/publish_platform/web/publish/commit/0cbed83b537a5b0a08f676256b8e69bb9ae0741a)
15
+ - 2026-03-02T14:38:28+08:00 [fix(chart): 组合图针对副轴数据全为0时,Y刻度的处理。](http://lf.git.oa.mt/publish_platform/web/publish/commit/2b262810e33d3660255831fb7ef0e345907841e9)
16
+
1
17
  **2.1.3** fix(chart): 组合图分组时inset置为0
2
18
  - 2026-02-28T23:48:20+08:00 [fix(chart): 组合图分组时inset置为0](http://lf.git.oa.mt/publish_platform/web/publish/commit/047e02d3cfbce21101277f48e904864163b2a02c)
3
19
  - 2026-02-28T22:42:20+08:00 [feat(chart): 组合图tooltip数据调整](http://lf.git.oa.mt/publish_platform/web/publish/commit/f79461050699b0755c8837e26b035083ec980cf1)
@@ -5,6 +5,7 @@ export interface TransformConfig {
5
5
  z?: string;
6
6
  isDescend?: boolean;
7
7
  isHorizontal?: boolean;
8
+ isGroup?: boolean;
8
9
  }
9
10
  /**
10
11
  * 数据适配器类
@@ -13,7 +14,7 @@ export declare class DataAdapter {
13
14
  /**
14
15
  * 统一的数据转换接口
15
16
  */
16
- static transform(data: any[], transformType: TransformConfig['type'], config: TransformConfig): any[];
17
+ static transform(data: any[], transformType: TransformConfig['type'], config: TransformConfig): any;
17
18
  /**
18
19
  * 柱状图数据转换
19
20
  */
@@ -30,10 +31,6 @@ export declare class DataAdapter {
30
31
  * 柱状折线组合图数据转换
31
32
  */
32
33
  private static transformForBarLine;
33
- /**
34
- * 分组柱状折线组合图数据转换
35
- */
36
- private static transformForGroupBarLine;
37
34
  /**
38
35
  * 分组对比图数据转换
39
36
  */
@@ -11,8 +11,6 @@ class DataAdapter {
11
11
  return this.transformForLine(data, config);
12
12
  case 'barLine':
13
13
  return this.transformForBarLine(data, config);
14
- case 'groupBarLine':
15
- return this.transformForGroupBarLine(data, config);
16
14
  case 'groupCompare':
17
15
  return this.transformForGroupCompare(data, config);
18
16
  default:
@@ -30,14 +28,16 @@ class DataAdapter {
30
28
  return row;
31
29
  }
32
30
  });
33
- if (config.isDescend) dv.transform({
34
- type: 'sort',
35
- callback: (a, b)=>{
31
+ if (config.isDescend) {
32
+ const compareData = dv.rows.filter((row)=>String(row.groupType ?? '').includes('_compare'));
33
+ const basicData = dv.rows.filter((row)=>!String(row.groupType ?? '').includes('_compare'));
34
+ basicData.sort((a, b)=>{
36
35
  if ('-' === a[config.y]) return config.isHorizontal ? -1 : 1;
37
36
  if ('-' === b[config.y]) return config.isHorizontal ? 1 : -1;
38
- return b[config.y] - a[config.y];
39
- }
40
- });
37
+ return config.isHorizontal ? a[config.y] - b[config.y] : b[config.y] - a[config.y];
38
+ });
39
+ dv.rows = basicData.concat(compareData);
40
+ }
41
41
  }
42
42
  return dv.rows;
43
43
  }
@@ -113,28 +113,10 @@ class DataAdapter {
113
113
  return dv.rows;
114
114
  }
115
115
  static transformForBarLine(data, config) {
116
- const ds = new lib();
117
- const dv = ds.createView().source(data);
118
- if (config.y) dv.transform({
119
- type: 'map',
120
- callback: (row)=>{
121
- row[config.y] = '' !== row[config.y] ? +row[config.y] : '-';
122
- return row;
123
- }
124
- });
125
- if (config.z) dv.transform({
126
- type: 'map',
127
- callback: (row)=>{
128
- row[config.z] = '' !== row[config.z] ? +row[config.z] : '-';
129
- return row;
130
- }
131
- });
132
- return dv.rows;
133
- }
134
- static transformForGroupBarLine(data, config) {
135
116
  const ds = new lib();
136
117
  const dv = ds.createView().source(data);
137
118
  const tdv = ds.createView().source(data);
119
+ const combinedv = ds.createView().source(data);
138
120
  if (config.y && config.x) {
139
121
  dv.transform({
140
122
  type: 'map',
@@ -156,28 +138,19 @@ class DataAdapter {
156
138
  return !row.isCombine;
157
139
  }
158
140
  });
159
- tdv.transform({
141
+ combinedv.transform({
160
142
  type: 'filter',
161
143
  callback (row) {
162
- return !row[config.y] || '-' !== row[config.y];
144
+ return row.isCombine;
163
145
  }
164
146
  });
165
147
  tdv.transform({
166
- type: 'aggregate',
167
- fields: [
168
- config.y
169
- ],
170
- groupBy: [
171
- config.x
172
- ],
173
- operations: [
174
- 'sum'
175
- ],
176
- as: [
177
- 'total'
178
- ]
148
+ type: 'filter',
149
+ callback (row) {
150
+ return !row[config.y] || '-' !== row[config.y];
151
+ }
179
152
  });
180
- tdv.transform({
153
+ if (config.isDescend) tdv.transform({
181
154
  type: 'sort',
182
155
  callback (a, b) {
183
156
  return b.total - a.total;
@@ -185,16 +158,15 @@ class DataAdapter {
185
158
  });
186
159
  const xKey = config.x ?? 'x';
187
160
  const sortData = tdv.rows.map((item)=>item[xKey]);
188
- if (config.isDescend) dv.transform({
189
- type: 'sort',
190
- callback (a, b) {
191
- if (-1 === sortData.indexOf(a[xKey])) return 1;
192
- if (-1 === sortData.indexOf(b[xKey])) return -1;
193
- return sortData.indexOf(a[xKey]) - sortData.indexOf(b[xKey]);
194
- }
195
- });
161
+ if (config.isDescend) combinedv.rows.sort((a, b)=>sortData.indexOf(a[xKey]) - sortData.indexOf(b[xKey]));
162
+ else combinedv.rows.sort((a, b)=>sortData.indexOf(a[xKey]) - sortData.indexOf(b[xKey]));
196
163
  }
197
- return dv.rows;
164
+ console.log('renderG2CombineChart transformedData:leftData:', tdv.rows, 'rightData:', combinedv.rows);
165
+ return {
166
+ transformedData: dv.rows,
167
+ leftData: tdv.rows,
168
+ rightData: combinedv.rows
169
+ };
198
170
  }
199
171
  static transformForGroupCompare(data, _config) {
200
172
  return data;
@@ -122,6 +122,7 @@ const G2BarChart = ({ height = 300, data, x = "", y = "", indicatorMap, onChartC
122
122
  isLegend: !!isCompare,
123
123
  isHorizontal,
124
124
  isHighlight,
125
+ isClickable: !!onChartClick,
125
126
  legend: safeLegend || void 0,
126
127
  formatLabel: isDataTag && safeY ? (d)=>{
127
128
  const v = d[safeY];
@@ -160,8 +161,11 @@ const G2BarChart = ({ height = 300, data, x = "", y = "", indicatorMap, onChartC
160
161
  });
161
162
  chartRef.current = chart;
162
163
  if (onChartClick) chart.on("element:click", (e)=>{
164
+ console.log('e:', e);
163
165
  const datum = e.data?.data;
164
- if (datum) onChartClick(datum);
166
+ if (datum) onChartClick({
167
+ title: datum[x]
168
+ });
165
169
  });
166
170
  return ()=>{
167
171
  if (chartRef.current) {
@@ -180,6 +184,7 @@ const G2BarChart = ({ height = 300, data, x = "", y = "", indicatorMap, onChartC
180
184
  isDataTag,
181
185
  isLegend,
182
186
  isHighlight,
187
+ isCompare,
183
188
  maxY,
184
189
  themeColors,
185
190
  safeIndicatorMap,
@@ -196,7 +201,7 @@ const G2BarChart = ({ height = 300, data, x = "", y = "", indicatorMap, onChartC
196
201
  position: "relative"
197
202
  },
198
203
  children: [
199
- isLegend && legendItems.length > 1 && 2 === nodeSetting.showType && /*#__PURE__*/ jsx(G2BarLegend, {
204
+ (isLegend || isCompare) && legendItems.length > 1 && 2 === nodeSetting.showType && /*#__PURE__*/ jsx(G2BarLegend, {
200
205
  items: legendItems,
201
206
  activeIds: activeIds,
202
207
  onChange: setActiveIds,
@@ -211,7 +216,7 @@ const G2BarChart = ({ height = 300, data, x = "", y = "", indicatorMap, onChartC
211
216
  height: `${height - canvasMarginBottom}px`
212
217
  }
213
218
  }),
214
- isLegend && legendItems.length > 1 && 2 !== nodeSetting.showType && /*#__PURE__*/ jsx(G2BarLegend, {
219
+ (isLegend || isCompare) && legendItems.length > 1 && 2 !== nodeSetting.showType && /*#__PURE__*/ jsx(G2BarLegend, {
215
220
  items: legendItems,
216
221
  activeIds: activeIds,
217
222
  onChange: setActiveIds,
@@ -17,14 +17,12 @@ const G2BarLegend = ({ items, activeIds, onChange, pageSize: pageSizeProp, maxLa
17
17
  const availableWidth = Math.max(0, width - pagerReserveWidth);
18
18
  const estimatedItemWidths = items.map((item)=>{
19
19
  const labelLength = item.label ? item.label.length : 0;
20
- console.log("computePageSize: estimatedItemWidths:", item.label, labelLength);
21
20
  const visibleChars = labelLength;
22
21
  return 16 + 8 * visibleChars;
23
22
  });
24
23
  const avgItemWidth = estimatedItemWidths.reduce((sum, w)=>sum + w, 0) / estimatedItemWidths.length;
25
24
  if (!avgItemWidth || !isFinite(avgItemWidth)) return void setAutoPageSize(items.length || 1);
26
25
  const computed = Math.max(1, Math.floor(availableWidth / avgItemWidth));
27
- console.log("computePageSize: computed:", computed, availableWidth, avgItemWidth, estimatedItemWidths);
28
26
  setAutoPageSize(computed);
29
27
  setPage((p)=>Math.min(p, Math.max(1, Math.ceil(items.length / computed))));
30
28
  };
@@ -51,6 +49,7 @@ const G2BarLegend = ({ items, activeIds, onChange, pageSize: pageSizeProp, maxLa
51
49
  ]);
52
50
  const handleToggle = (id)=>{
53
51
  const isActive = activeIds.includes(id);
52
+ if (isActive && activeIds.length <= 1) return;
54
53
  const nextSet = new Set(isActive ? activeIds.filter((x)=>x !== id) : [
55
54
  ...activeIds,
56
55
  id
@@ -63,68 +63,65 @@ const G2CombineChart = ({ height = 300, data, x = "", y = "", z = "", indicatorM
63
63
  }, indicators = [], auxiliaryLineData, highlightDate, timeRange, isGroup })=>{
64
64
  const { formatter, dataTransform, config: contextConfig } = useChartContext();
65
65
  const tooltipContainerRef = useG2TooltipContainer();
66
+ const isGroupRef = useRef(isGroup);
67
+ const [isOldData, setIsOldData] = useState(false);
68
+ isGroupRef.current = isGroup;
66
69
  console.log("G2CombineChart props:", data, x, y, z, indicators, legend, config, nodeSetting);
67
70
  const themeColors = contextConfig?.theme?.colors || [];
68
71
  const safeIndicatorMap = indicatorMap || contextConfig.indicatorMap || {};
69
- const safeLegend = useMemo(()=>{
70
- if (isGroup) return legend || 'groupType';
71
- if ("groupType" === legend) return y;
72
- return legend || y;
73
- }, [
74
- isGroup,
75
- legend,
76
- y
77
- ]);
72
+ const safeLegend = legend || "groupType";
78
73
  const safeZ = z;
79
74
  const safeY = "groupValue";
80
75
  const isCompare = timeRange?.compareStartTime !== "";
81
76
  const chartConfig = config || {};
82
- const { isDataTag = false, isLegend = true, isDescend = false } = chartConfig;
77
+ const { isDataTag = true, isCombineDataTag = true, isLegend = true, isDescend = false, isHighlight = true } = chartConfig;
83
78
  const [xyList, setXYList] = useState([]);
84
79
  const [activeIds, setActiveIds] = useState([]);
85
80
  const [legendItems, setLegendItems] = useState([]);
86
- const transformedData = useMemo(()=>{
81
+ const { transformedData, leftData, rightData } = useMemo(()=>{
82
+ console.log("G2CombineChart left useMemo: legend:", legend, data, x, y, z, indicators);
87
83
  if (!legend) {
88
84
  let result = transformDataToGroupBarLineFormat(data, x, y, indicators);
89
85
  data = result;
86
+ setIsOldData(true);
90
87
  }
91
- console.log("G2CombineChart transformedData2:", data);
92
- const result = isGroup ? DataAdapter.transform(data, "groupBarLine", {
88
+ console.log("G2CombineChart renderG2CombineChart transformedData2:", data);
89
+ const { transformedData, leftData, rightData } = DataAdapter.transform(data, "barLine", {
93
90
  type: "barLine",
94
91
  x,
95
92
  y: safeY,
96
- isDescend
97
- }) : DataAdapter.transform(data, "barLine", {
98
- type: "barLine",
99
- x,
100
- y: safeY,
101
- z
93
+ z,
94
+ isDescend,
95
+ isGroup: isGroupRef.current
102
96
  });
103
- return result.map((item)=>dataTransform.processNodeInfo(item, contextConfig.nodeMap));
97
+ return {
98
+ transformedData: transformedData.map((item)=>dataTransform.processNodeInfo(item, contextConfig.nodeMap)),
99
+ leftData: leftData.map((item)=>dataTransform.processNodeInfo(item, contextConfig.nodeMap)),
100
+ rightData: rightData.map((item)=>dataTransform.processNodeInfo(item, contextConfig.nodeMap))
101
+ };
104
102
  }, [
105
- isGroup,
106
103
  data,
107
104
  x,
108
105
  safeY,
109
106
  z,
110
107
  dataTransform,
111
- contextConfig.nodeMap
108
+ contextConfig.nodeMap,
109
+ isDescend
112
110
  ]);
113
- console.log("G2CombineChart transformedData:", transformedData);
111
+ console.log("G2CombineChart transformedData:", transformedData, leftData, rightData);
114
112
  const { maxY } = useMemo(()=>{
115
- const key = isGroup ? "total" : safeY;
113
+ const key = isGroupRef.current ? "total" : safeY;
116
114
  const yValues = transformedData.filter((item)=>"-" !== item[key] && void 0 !== item[key] && null !== item[key]).map((item)=>Number(item[key]) || 0);
117
115
  return {
118
116
  maxY: yValues.length > 0 ? Math.max(...yValues) : 0
119
117
  };
120
118
  }, [
121
- isGroup,
122
119
  transformedData,
123
120
  safeY
124
121
  ]);
125
- const formatAxis = useCallback((val)=>getAxisFormat(val, safeIndicatorMap, safeLegend), [
122
+ const formatAxis = useCallback((val)=>getAxisFormat(val, safeIndicatorMap, y), [
126
123
  safeIndicatorMap,
127
- safeLegend
124
+ y
128
125
  ]);
129
126
  const formatLineAxis = useCallback((val)=>getAxisFormat(val, safeIndicatorMap, safeZ), [
130
127
  safeIndicatorMap,
@@ -143,31 +140,53 @@ const G2CombineChart = ({ height = 300, data, x = "", y = "", z = "", indicatorM
143
140
  const indicatorId = id.split("_")[0];
144
141
  const isCombine = "true" === id.split("_")[1];
145
142
  const lineGroupTypeIndex = lineGroupTypeArr.indexOf(id);
146
- const color = isGroup ? isCombine ? lineColors[lineGroupTypeIndex] || lineColors[0] : themeColors[colorIndex] || themeColors[0] : 0 === colorIndex ? themeColors[colorIndex] : lineColors[colorIndex - 1];
143
+ const color = isGroupRef.current ? isCombine ? lineColors[lineGroupTypeIndex] || lineColors[0] : themeColors[colorIndex] || themeColors[0] : 0 === colorIndex ? themeColors[colorIndex] : lineColors[colorIndex - 1];
147
144
  return {
148
145
  id,
149
- label: isGroup ? isCombine ? getIndicatorCompareName(safeIndicatorMap, String(indicatorId)) : indicatorId : getIndicatorCompareName(safeIndicatorMap, String(indicatorId)) + (String(indicatorId).includes("_compare") ? `(对比时间:${timeRange?.compareStartTime}~${timeRange?.compareEndTime})` : ""),
146
+ label: isGroupRef.current ? isCombine ? getIndicatorCompareName(safeIndicatorMap, String(indicatorId)) : indicatorId : getIndicatorCompareName(safeIndicatorMap, String(indicatorId)) + (String(indicatorId).includes("_compare") ? `(对比时间:${timeRange?.compareStartTime}~${timeRange?.compareEndTime})` : ""),
150
147
  color,
151
148
  isCompare: String(indicatorId).includes("_compare"),
152
- symbol: isGroup ? isCombine ? 'line' : 'square' : 0 === colorIndex ? "square" : "line"
149
+ symbol: isGroupRef.current ? isCombine ? "line" : "square" : 0 === colorIndex ? "square" : "line"
153
150
  };
154
151
  });
155
152
  setLegendItems(items);
156
- if (!activeIds.length) setActiveIds(items.map((i)=>i.id));
153
+ const newIds = items.map((i)=>i.id);
154
+ setActiveIds((prev)=>{
155
+ if (!prev.length) return newIds;
156
+ const newSet = new Set(newIds);
157
+ if (prev.length !== newIds.length || prev.some((id)=>!newSet.has(id))) return newIds;
158
+ return prev;
159
+ });
157
160
  }, [
158
- isGroup,
159
161
  transformedData,
160
162
  safeIndicatorMap,
161
- themeColors,
162
- activeIds.length
163
+ themeColors
163
164
  ]);
164
- const filteredData = useMemo(()=>{
165
- if (!activeIds.length) return transformedData;
166
- return transformedData.filter((d)=>d.groupType ? activeIds.includes(String(d.groupType.replace("_compare", "") + "_" + d.isCombine)) : true);
165
+ const filterLeftData = useMemo(()=>{
166
+ if (!activeIds.length) return leftData;
167
+ const result = leftData.filter((d)=>d.groupType ? activeIds.includes(String(d.groupType.replace("_compare", "") + "_" + d.isCombine)) : true);
168
+ if (isGroupRef.current) result.forEach((item)=>{
169
+ item.total = result.filter((d)=>d.groupName === item.groupName).reduce((acc, d)=>acc + d.groupValue, 0);
170
+ });
171
+ return result;
167
172
  }, [
168
- transformedData,
173
+ leftData,
174
+ activeIds
175
+ ]);
176
+ const filterRightData = useMemo(()=>{
177
+ if (!activeIds.length) return rightData;
178
+ return rightData.filter((d)=>d.groupType ? activeIds.includes(String(d.groupType.replace("_compare", "") + "_" + d.isCombine)) : true);
179
+ }, [
180
+ rightData,
169
181
  activeIds
170
182
  ]);
183
+ const filteredData = useMemo(()=>[
184
+ ...filterLeftData,
185
+ ...filterRightData
186
+ ], [
187
+ filterLeftData,
188
+ filterRightData
189
+ ]);
171
190
  const canvasMarginBottom = legendItems.length > 1 ? 2 === nodeSetting.showType ? 32 : 16 : 0;
172
191
  const containerRef = useRef(null);
173
192
  const chartRef = useRef(null);
@@ -192,12 +211,17 @@ const G2CombineChart = ({ height = 300, data, x = "", y = "", z = "", indicatorM
192
211
  formatAxis,
193
212
  formatLineAxis,
194
213
  isDataTag,
214
+ isCombineDataTag,
195
215
  isLegend: false,
196
216
  isCompare,
217
+ isHighlight,
218
+ isClickable: !!onChartClick,
197
219
  height: height - canvasMarginBottom,
198
- formatLabel: isDataTag ? (d)=>{
220
+ formatLabel: (isDataTag || isCombineDataTag) && !isOldData ? (d)=>{
199
221
  const indicatorId = d.groupType.split("_")[0];
200
- return isGroup ? d.isCombine ? "-" === formatter.formatIndicator(d.groupValue, safeIndicatorMap[z]) ? "" : formatter.formatIndicator(d.groupValue, safeIndicatorMap[z]) : "-" === formatter.formatIndicator(d['total'], safeIndicatorMap[y]) ? "" : formatter.formatIndicator(d['total'], safeIndicatorMap[y]) : "-" === formatter.formatIndicator(d.groupValue, safeIndicatorMap[indicatorId]) ? "" : formatter.formatIndicator(d.groupValue, safeIndicatorMap[indicatorId]);
222
+ const key = isGroupRef.current && !d.isCombine ? "total" : indicatorId;
223
+ if ("total" === key) return formatter.formatIndicator(d.total, safeIndicatorMap[y]);
224
+ return formatter.formatIndicator(d.groupValue, safeIndicatorMap[key]);
201
225
  } : void 0,
202
226
  indicators,
203
227
  tooltipRender: (title, items)=>{
@@ -209,7 +233,7 @@ const G2CombineChart = ({ height = 300, data, x = "", y = "", z = "", indicatorM
209
233
  }));
210
234
  safeItems = safeItems.filter((i)=>i.indicatorId);
211
235
  react_dom.render(/*#__PURE__*/ jsx(G2CompareTooltip, {
212
- isGroupBar: isGroup,
236
+ isGroupBar: isGroupRef.current,
213
237
  title: title,
214
238
  items: safeItems,
215
239
  safeIndicatorMap: safeIndicatorMap,
@@ -221,6 +245,7 @@ const G2CombineChart = ({ height = 300, data, x = "", y = "", z = "", indicatorM
221
245
  },
222
246
  highlightDate: highlightDate ?? [],
223
247
  timeRange,
248
+ auxiliaryLineData: auxiliaryLineData ?? [],
224
249
  onNodeListChange: (nodes)=>{
225
250
  setXYList(nodes);
226
251
  },
@@ -232,14 +257,16 @@ const G2CombineChart = ({ height = 300, data, x = "", y = "", z = "", indicatorM
232
257
  }
233
258
  },
234
259
  lineColors,
235
- isGroup,
236
260
  legendItems,
237
- indicatorId: y
261
+ indicatorId: y,
262
+ isGroup: isGroupRef.current
238
263
  });
239
264
  chartRef.current = chart;
240
265
  if (onChartClick) chart.on("element:click", (e)=>{
241
266
  const datum = e.data?.data;
242
- if (datum) onChartClick(datum);
267
+ if (datum) onChartClick({
268
+ title: datum[x]
269
+ });
243
270
  });
244
271
  return ()=>{
245
272
  if (chartRef.current) {
@@ -256,23 +283,22 @@ const G2CombineChart = ({ height = 300, data, x = "", y = "", z = "", indicatorM
256
283
  z,
257
284
  maxY,
258
285
  isDataTag,
259
- isLegend,
286
+ isCombineDataTag,
287
+ isDescend,
260
288
  themeColors,
261
289
  safeIndicatorMap,
262
290
  formatter,
263
291
  formatAxis,
264
292
  onChartClick,
265
- isGroup,
266
- legendItems
293
+ isLegend,
294
+ isHighlight,
295
+ legendItems,
296
+ auxiliaryLineData,
297
+ leftData,
298
+ rightData,
299
+ isOldData
267
300
  ]);
268
- if (!z) return /*#__PURE__*/ jsx("div", {
269
- style: {
270
- width: "100%",
271
- color: "#86909c",
272
- padding: 16
273
- },
274
- children: "请传入 z 作为折线指标字段,以展示柱状+折线组合图。"
275
- });
301
+ console.log("G2BarLegend items: combie", legendItems, activeIds);
276
302
  return /*#__PURE__*/ jsxs("div", {
277
303
  style: {
278
304
  width: "100%",
@@ -12,11 +12,11 @@ import useG2TooltipContainer from "../shared/useG2TooltipContainer.js";
12
12
  import { getIndicatorCompareName } from "../../../utils/indicatorHelpers.js";
13
13
  import { G2BarLegend } from "./G2BarLegend.js";
14
14
  import { renderG2LineChart } from "./g2line.js";
15
- const G2LineChart = ({ height = 300, data, x = "", y = "", z = "", indicatorMap, onChartClick: _onChartClick, timeRange, legend = "", config, nodeSetting = {
15
+ const G2LineChart = ({ height = 300, data, x = "", y = "", z = "", indicatorMap, onChartClick, timeRange, legend = "", config, nodeSetting = {
16
16
  showType: 0,
17
17
  type: []
18
18
  }, auxiliaryLineData, highlightDate, indicators = [] })=>{
19
- console.log("props data: G2LineChart", data, nodeSetting, config, "x, y, z", x, y, z, "highlightDate:", highlightDate);
19
+ console.log("props data: G2LineChart", data, nodeSetting, config, "x, y, z", x, y, z, "highlightDate:", highlightDate, "indicators:", indicators);
20
20
  const { formatter, dataTransform, config: contextConfig } = useChartContext();
21
21
  const tooltipContainerRef = useG2TooltipContainer();
22
22
  const themeColors = contextConfig?.theme?.colors || [];
@@ -94,12 +94,17 @@ const G2LineChart = ({ height = 300, data, x = "", y = "", z = "", indicatorMap,
94
94
  };
95
95
  });
96
96
  setLegendItems(items);
97
- if (!activeIds.length) setActiveIds(items.map((i)=>i.id));
97
+ const newIds = items.map((i)=>i.id);
98
+ setActiveIds((prev)=>{
99
+ if (!prev.length) return newIds;
100
+ const newSet = new Set(newIds);
101
+ if (prev.length !== newIds.length || prev.some((id)=>!newSet.has(id))) return newIds;
102
+ return prev;
103
+ });
98
104
  }, [
99
105
  transformedData,
100
106
  safeIndicatorMap,
101
- themeColors,
102
- activeIds.length
107
+ themeColors
103
108
  ]);
104
109
  const filteredData = useMemo(()=>{
105
110
  if (!activeIds.length) return transformedData;
@@ -123,7 +128,7 @@ const G2LineChart = ({ height = 300, data, x = "", y = "", z = "", indicatorMap,
123
128
  minY,
124
129
  maxY,
125
130
  themeColors,
126
- indicators,
131
+ indicators: indicators || activeIds,
127
132
  indicatorMap: safeIndicatorMap,
128
133
  formatAxis,
129
134
  highlightDate: highlightDate ?? [],
@@ -169,6 +174,12 @@ const G2LineChart = ({ height = 300, data, x = "", y = "", z = "", indicatorMap,
169
174
  }
170
175
  });
171
176
  chartRef.current = chart;
177
+ if (onChartClick) chart.on("element:click", (e)=>{
178
+ const datum = e.data?.data;
179
+ if (datum) onChartClick({
180
+ title: datum[x]
181
+ });
182
+ });
172
183
  return ()=>{
173
184
  if (chartRef.current) {
174
185
  chartRef.current.off("element:click");
@@ -216,6 +216,7 @@ export interface ScaleYLinearOptions {
216
216
  export declare function applyScaleYLinear(view: any, options?: ScaleYLinearOptions): void;
217
217
  export interface ApplyAxisXOptions {
218
218
  title?: boolean;
219
+ isHorizontal?: boolean;
219
220
  labelAutoHide?: 'greedy' | 'equidistant' | boolean;
220
221
  /** 为 true 时刻度过多会自动旋转为垂直;为 false 时保持水平,依赖 labelAutoHide 避免重叠。默认 false */
221
222
  labelAutoRotate?: boolean;
@@ -271,6 +272,7 @@ export declare function applyLegendColor(view: any, options?: ApplyLegendColorOp
271
272
  export interface AuxiliaryLineItem {
272
273
  name: string;
273
274
  value: number;
275
+ axis?: 'left' | 'right';
274
276
  }
275
277
  export interface ApplyAuxiliaryLineYOptions {
276
278
  stroke?: string;
@@ -291,3 +293,4 @@ export interface GetColorByGroupTypeOptions {
291
293
  */
292
294
  export declare function getColorByGroupType(groupType: string, options: GetColorByGroupTypeOptions): string;
293
295
  export declare function applyHighlightDate(view: any, x: string, data: any, highlightDate: string[], isHighlight: boolean): void;
296
+ export declare function adjustDomainMax(domainMin: number, domainMax: number): number;
@@ -19,7 +19,7 @@ function applyScaleYLinear(view, options = {}) {
19
19
  [field]: {
20
20
  type: 'linear',
21
21
  ...null != domainMax && {
22
- domainMax
22
+ domainMax: adjustDomainMax(domainMin, domainMax)
23
23
  },
24
24
  domainMin,
25
25
  clamp,
@@ -38,7 +38,7 @@ function applyScaleYLinear(view, options = {}) {
38
38
  });
39
39
  }
40
40
  function applyAxisX(mark, options = {}) {
41
- const { title = false, labelAutoRotate = false, grid = true, gridStroke = '#333', gridLineWidth = 50, gridLineDash = [
41
+ const { title = false, grid = true, gridStroke = '#333', gridLineWidth = 50, gridLineDash = [
42
42
  1000
43
43
  ], gridFilter } = options;
44
44
  mark.axis('x', {
@@ -50,16 +50,19 @@ function applyAxisX(mark, options = {}) {
50
50
  ...gridFilter && {
51
51
  gridFilter
52
52
  },
53
+ labelAutoRotate: false,
54
+ labelFontSize: 12,
55
+ labelFontColor: '#000',
56
+ labelAutoEllipsis: {
57
+ type: 'ellipsis',
58
+ maxLength: 50
59
+ },
60
+ labelAlign: 'horizontal',
53
61
  labelAutoHide: {
54
62
  type: 'hide',
55
63
  keepHeader: true,
56
64
  keepTail: true
57
- },
58
- labelAutoRotate,
59
- labelFontSize: 12,
60
- labelFontColor: '#000',
61
- labelAutoEllipsis: true,
62
- labelFontOpacity: 1
65
+ }
63
66
  });
64
67
  }
65
68
  function applyAxisY(mark, options = {}) {
@@ -123,11 +126,16 @@ function applyAuxiliaryLineY(view, lines, options = {}) {
123
126
  console.log('applyAuxiliaryLineY:', lines);
124
127
  const { stroke = '#F4664A', strokeOpacity = 1, labelMaxLength = 5 } = options;
125
128
  lines.forEach((auxLine)=>{
126
- view.lineY().encode('y', auxLine.value).style('stroke', stroke).style('strokeOpacity', strokeOpacity).style('lineWidth', 1).style('shadowColor', 'transparent').label({
129
+ view.lineY().encode('y', auxLine.value).style('stroke', stroke).style('strokeOpacity', strokeOpacity).style('lineWidth', 1).style('shadowColor', 'transparent').axis('y', {
130
+ title: false,
131
+ grid: false,
132
+ label: false,
133
+ tick: false
134
+ }).label({
127
135
  dx: 0,
128
136
  dy: -5,
129
137
  text: splitTextToMultiline(auxLine.name, labelMaxLength, '<br />'),
130
- position: 'bottom-left',
138
+ position: auxLine?.axis === 'right' ? 'bottom-right' : 'bottom-left',
131
139
  style: {},
132
140
  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>`
133
141
  });
@@ -179,4 +187,7 @@ function applyHighlightDate(view, x, data, highlightDate, isHighlight) {
179
187
  strokeOpacity: 0
180
188
  });
181
189
  }
182
- export { applyAuxiliaryLineY, applyAxisX, applyAxisY, applyHighlightDate, applyLegendColor, applyScaleYLinear, createChart, getColorByGroupType, getMainView };
190
+ function adjustDomainMax(domainMin, domainMax) {
191
+ return domainMax === domainMin ? domainMin > 0 ? 1.1 * domainMax : domainMax + 1 : domainMax;
192
+ }
193
+ export { adjustDomainMax, applyAuxiliaryLineY, applyAxisX, applyAxisY, applyHighlightDate, applyLegendColor, applyScaleYLinear, createChart, getColorByGroupType, getMainView };
@@ -33,6 +33,8 @@ export interface RenderG2BarChartOptions {
33
33
  isHighlight?: boolean;
34
34
  /** 图例字段名(与 y 不同时表示分组柱),通常为 groupType */
35
35
  isCompare?: boolean;
36
+ /** 是否启用点击事件 */
37
+ isClickable?: boolean;
36
38
  legend?: string;
37
39
  /** 数据标签格式化:formatLabel(datum) */
38
40
  formatLabel?: (datum: any) => string;
@@ -2,7 +2,7 @@ import { lines } from "@antv/g-pattern";
2
2
  import { applyAuxiliaryLineY, applyAxisX, applyAxisY, applyHighlightDate, applyScaleYLinear, createChart, getColorByGroupType, getMainView } from "./g2Helpers.js";
3
3
  const Y_AXIS_FIELD = 'groupValue';
4
4
  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, legend, formatLabel, height = 300, tooltipRender, auxiliaryLineData = [], onNodeListChange, onChartRender } = 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;
6
6
  const colorOpts = {
7
7
  themeColors,
8
8
  primaryKey: y,
@@ -20,7 +20,7 @@ function renderG2BarChart(container, options) {
20
20
  });
21
21
  console.log('isLegend:', legend, isLegend);
22
22
  const view = getMainView(chart);
23
- view.attr('marginBottom', isLegend ? 0 : 16);
23
+ view.attr('marginLeft', 0).attr('marginBottom', isLegend ? 0 : 16);
24
24
  if (isHorizontal) view.coordinate({
25
25
  transform: [
26
26
  {
@@ -46,13 +46,13 @@ function renderG2BarChart(container, options) {
46
46
  columnWidthRatio: 0.6,
47
47
  insetLeft: (_d, index, _data, _column)=>{
48
48
  if (isHorizontal) return 0;
49
- if (isCompare) return index % 2 === 0 ? 4 : 0;
50
- return 4;
49
+ if (isCompare) return index % 2 === 0 ? 0 : 0;
50
+ return 0;
51
51
  },
52
52
  insetRight: (_d, index, _data, _column)=>{
53
53
  if (isHorizontal) return 0;
54
- if (isCompare) return index % 2 === 1 ? 4 : 0;
55
- return 4;
54
+ if (isCompare) return index % 2 === 1 ? 0 : 0;
55
+ return 0;
56
56
  },
57
57
  fill: (datum)=>{
58
58
  const groupType = String(datum.groupType ?? '');
@@ -68,10 +68,12 @@ function renderG2BarChart(container, options) {
68
68
  transform: 'rotate(-30deg)'
69
69
  };
70
70
  return getColorByGroupType(groupType, colorOpts);
71
- }
71
+ },
72
+ cursor: isClickable ? 'pointer' : 'default'
72
73
  });
73
74
  applyAxisX(view, {
74
- grid: false
75
+ grid: false,
76
+ isHorizontal
75
77
  });
76
78
  applyAxisY(view, {
77
79
  labelFormatter: formatAxis
@@ -4,6 +4,7 @@
4
4
  */
5
5
  import { Chart } from "@antv/g2";
6
6
  import type { ChartTimeRange, IndicatorInfo } from "../../../core/ChartTypes";
7
+ import { type AuxiliaryLineItem } from "./g2Helpers";
7
8
  export interface RenderG2CombineChartOptions {
8
9
  /** 已转换后的数据:约定包含 groupName、groupType、groupValue 等字段 */
9
10
  data: any[];
@@ -27,12 +28,16 @@ export interface RenderG2CombineChartOptions {
27
28
  formatLineAxis: (val: any) => string;
28
29
  /** 是否显示数据标签 */
29
30
  isDataTag?: boolean;
31
+ /** 是否显示副轴数据标签 */
32
+ isCombineDataTag?: boolean;
30
33
  /** 是否显示自定义 Legend(仅影响 React 层,G2 内部不画 legend) */
31
34
  isLegend?: boolean;
32
35
  /** 是否启用图例高亮 */
33
36
  isHighlight?: boolean;
34
37
  /** 是否启用对比期 */
35
38
  isCompare?: boolean;
39
+ /** 是否启用点击事件 */
40
+ isClickable?: boolean;
36
41
  /** 数据标签格式化:formatLabel(datum) */
37
42
  formatLabel?: (datum: any) => string;
38
43
  /** 图表高度 */
@@ -49,6 +54,8 @@ export interface RenderG2CombineChartOptions {
49
54
  isChange?: boolean;
50
55
  compareTime?: string;
51
56
  }>) => HTMLElement | null;
57
+ /** 辅助线 */
58
+ auxiliaryLineData?: AuxiliaryLineItem[];
52
59
  /** 将计算出的节点信息传递给外层(用于渲染 NodePopover 等) */
53
60
  onNodeListChange?: (nodes: Array<{
54
61
  pointP: {
@@ -1,11 +1,11 @@
1
1
  import { lines } from "@antv/g-pattern";
2
- import { applyAxisX, applyHighlightDate, createChart, getMainView } from "./g2Helpers.js";
2
+ import { applyAuxiliaryLineY, applyAxisX, applyHighlightDate, 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 = false, isLegend: _isLegend = false, isCompare = false, formatLabel, highlightDate = [], height = 300, isHighlight = true, indicators = [], tooltipRender, onNodeListChange, lineColors, onChartRender, isGroup, legendItems = [], indicatorId } = 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;
9
9
  const chart = createChart({
10
10
  container,
11
11
  height,
@@ -17,7 +17,7 @@ function renderG2CombineChart(container, options) {
17
17
  insetBottom: 0
18
18
  });
19
19
  const view = getMainView(chart);
20
- view.attr('marginBottom', 0);
20
+ view.attr('insetLeft', 0).attr('insetRight', 0).attr('marginLeft', 0).attr('marginRight', 0).attr('marginBottom', 0);
21
21
  console.log('renderG2CombineChart data:', data, 'maxY:', maxY, x, y, 'indicators:', indicators);
22
22
  view.data(data);
23
23
  applyAxisX(view, {
@@ -26,16 +26,20 @@ function renderG2CombineChart(container, options) {
26
26
  });
27
27
  const barColor = themeColors[0] ?? "#5B8FF9";
28
28
  console.log('tooltip: themeColors:', themeColors[0], barColor, isGroup);
29
- console.log('renderG2CombineChart interval data:', data.filter((item)=>!item.isCombine));
29
+ console.log('renderG2CombineChart highlightDate:', highlightDate, isHighlight);
30
30
  applyHighlightDate(view, x, data, highlightDate, isHighlight);
31
31
  const intervalData = data.filter((item)=>!item.isCombine).map((item)=>({
32
32
  ...item,
33
33
  [BAR_Y_FIELD]: item[Y_AXIS_FIELD]
34
34
  }));
35
+ console.log('renderG2CombineChart interval data:', intervalData);
35
36
  const intervalMaxY = intervalData.reduce((max, item)=>{
36
37
  const key = isGroup ? "total" : BAR_Y_FIELD;
37
38
  return Math.max(max, item[key]);
38
39
  }, 0);
40
+ const auxValues = auxiliaryLineData?.length ? auxiliaryLineData.map((item)=>item.value) : [];
41
+ const maxAux = auxValues.length ? Math.max(...auxValues) : 0;
42
+ const finalIntervalMax = Math.max(intervalMaxY, maxAux);
39
43
  const interval = view.interval().data(intervalData).encode("x", x).encode("y", BAR_Y_FIELD).encode("color", "groupType").transform(isGroup ? {
40
44
  type: 'stackY',
41
45
  reverse: true
@@ -71,12 +75,13 @@ function renderG2CombineChart(container, options) {
71
75
  };
72
76
  return barColor;
73
77
  },
78
+ cursor: isClickable ? 'pointer' : 'default',
74
79
  stroke: 'transparent'
75
80
  });
76
81
  interval.scale('y', {
77
82
  type: 'linear',
78
83
  domainMin: 0,
79
- domainMax: intervalMaxY,
84
+ domainMax: finalIntervalMax,
80
85
  nice: true,
81
86
  clamp: true,
82
87
  key: 'bar',
@@ -103,6 +108,7 @@ function renderG2CombineChart(container, options) {
103
108
  (datum)=>{
104
109
  const groupType = String(datum.groupType ?? '');
105
110
  const index = legendItems.findIndex((item)=>item.id === `${groupType}_${datum.isCombine}`);
111
+ console.log(datum);
106
112
  return {
107
113
  value: datum[Y_AXIS_FIELD],
108
114
  name: datum['groupType'],
@@ -141,11 +147,11 @@ function renderG2CombineChart(container, options) {
141
147
  } : false : false
142
148
  ].filter(Boolean)
143
149
  });
144
- console.log('renderG2CombineChart: line data:', data.filter((item)=>item.isCombine));
145
150
  const lineData = data.filter((item)=>item.isCombine && !item.groupType.includes('_compare')).map((item)=>({
146
151
  ...item,
147
152
  [LINE_Y_FIELD]: item[Y_AXIS_FIELD]
148
153
  }));
154
+ console.log('renderG2CombineChart: line data:', lineData);
149
155
  const compareLineData = data.filter((item)=>item.isCombine && item.groupType.includes('_compare')).map((item)=>({
150
156
  ...item,
151
157
  [LINE_Y_FIELD]: item[Y_AXIS_FIELD]
@@ -153,8 +159,8 @@ function renderG2CombineChart(container, options) {
153
159
  console.log('compareLineData:', compareLineData);
154
160
  const lineMaxY = lineData.reduce((max, item)=>Math.max(max, item[LINE_Y_FIELD]), 0);
155
161
  const compareLineMaxY = compareLineData.reduce((max, item)=>Math.max(max, item[LINE_Y_FIELD]), 0);
156
- const lineFinalMaxY = Math.max(lineMaxY, compareLineMaxY);
157
- console.log('lineFinalMaxY:', lineFinalMaxY);
162
+ const lineFinalMaxY = Math.max(lineMaxY, compareLineMaxY) || 1;
163
+ const finalLineMax = Math.max(lineFinalMaxY, maxAux);
158
164
  const line = view.line().data(lineData).encode("x", x).encode("y", LINE_Y_FIELD).encode('color', 'groupType').style({
159
165
  lineWidth: 2,
160
166
  stroke: (datum)=>{
@@ -164,7 +170,7 @@ function renderG2CombineChart(container, options) {
164
170
  ];
165
171
  const groupType = String(datum[0]?.groupType ?? '');
166
172
  const index = groupTypeArr.findIndex((item)=>item === groupType);
167
- const color = isGroup ? lineColors[index] || lineColors[0] : lineColors[indicators.slice(1).indexOf(String(groupType)) ?? 0];
173
+ const color = lineColors[index] || lineColors[0];
168
174
  return color;
169
175
  }
170
176
  });
@@ -175,14 +181,14 @@ function renderG2CombineChart(container, options) {
175
181
  const groupTypeArr = [
176
182
  ...groupTypeSet
177
183
  ];
178
- const groupType = String(datum[0]?.groupType ?? '');
184
+ const groupType = String(datum?.groupType ?? '');
179
185
  const index = groupTypeArr.findIndex((item)=>item === groupType);
180
186
  return {
181
187
  value: datum[LINE_Y_FIELD],
182
- name: isGroup ? getIndicatorCompareName(_indicatorMap, datum['groupType']) : datum['groupType'],
188
+ name: getIndicatorCompareName(_indicatorMap, datum['groupType']),
183
189
  indicatorId: datum['groupType'],
184
190
  channel: Y_AXIS_FIELD,
185
- color: isGroup ? lineColors[index] || lineColors[0] : lineColors[indicators.slice(1).indexOf(String(datum['groupType'])) ?? 0] || 'transparent',
191
+ color: lineColors[index] || lineColors[0],
186
192
  isCombine: true,
187
193
  tipType: 'line'
188
194
  };
@@ -192,10 +198,10 @@ function renderG2CombineChart(container, options) {
192
198
  line.scale('y', {
193
199
  type: 'linear',
194
200
  domainMin: 0,
195
- domainMax: lineFinalMaxY,
201
+ domainMax: finalLineMax,
196
202
  nice: true,
197
203
  clamp: true,
198
- key: 'bar',
204
+ key: 'line',
199
205
  independent: true,
200
206
  tickMethod: (min, max)=>Array.from({
201
207
  length: 6
@@ -221,15 +227,23 @@ function renderG2CombineChart(container, options) {
221
227
  4
222
228
  ],
223
229
  lineWidth: 2,
224
- stroke: (datum, index)=>{
230
+ stroke: (datum)=>{
225
231
  const groupType = String(datum[0]?.groupType ?? '');
226
232
  const color = lineColors[indicators.slice(1).indexOf(String(groupType.replace('_compare', ''))) ?? 0];
227
- console.log('compareLine: 222', 'index:', index, 'indicators:', indicators, 'datum:', datum, 'groupType:', groupType, 'color:', color);
228
233
  return color ?? 'transparent';
229
234
  }
230
235
  });
231
236
  compareLine.scale('y', {
232
- key: 'line'
237
+ type: 'linear',
238
+ domainMin: 0,
239
+ domainMax: finalLineMax,
240
+ nice: true,
241
+ clamp: true,
242
+ key: 'line',
243
+ independent: true,
244
+ tickMethod: (min, max)=>Array.from({
245
+ length: 6
246
+ }, (_, i)=>min + (max - min) * i / 5)
233
247
  });
234
248
  compareLine.axis('y', false);
235
249
  const hasCompareData = data.some((item)=>item.groupType.includes('_compare'));
@@ -265,33 +279,31 @@ function renderG2CombineChart(container, options) {
265
279
  const { title, items } = payload;
266
280
  const baseItems = items.filter((item)=>!item.isCombine);
267
281
  const combineItems = items.filter((item)=>item.isCombine);
268
- console.log('tooltipRender:', title, items, indicators);
269
- if (isGroup) return tooltipRender(title, [
270
- ...baseItems,
282
+ const indicatorOrder = new Map(indicators.map((id, i)=>[
283
+ id,
284
+ i
285
+ ]));
286
+ const sortedCombineItems = [
271
287
  ...combineItems
288
+ ].sort((a, b)=>{
289
+ const orderA = indicatorOrder.get(a.indicatorId) ?? 1 / 0;
290
+ const orderB = indicatorOrder.get(b.indicatorId) ?? 1 / 0;
291
+ if (orderA !== orderB) return orderA - orderB;
292
+ const typeRank = (item)=>{
293
+ if (item.isChange) return 2;
294
+ if ('compareline' === item.tipType) return 1;
295
+ return 0;
296
+ };
297
+ return typeRank(a) - typeRank(b);
298
+ });
299
+ return tooltipRender(title, [
300
+ ...baseItems,
301
+ ...sortedCombineItems
272
302
  ]) ?? null;
273
- if (indicators.length) {
274
- const groupedItems = indicators.map((indicator, index)=>{
275
- if (0 === index) return items.filter((i)=>!i.isCombine).filter((i)=>i.indicatorId === String(indicator));
276
- return items.filter((i)=>i.isCombine).filter((i)=>i.indicatorId === String(indicator));
277
- });
278
- console.log(groupedItems.flat(), 'tooltip groupedItems');
279
- const sortedItems = groupedItems.map((group)=>[
280
- group.filter((i)=>i.name === i.indicatorId),
281
- group.filter((i)=>i.compareTime),
282
- group.filter((i)=>i.name.includes('_change'))
283
- ].filter(Boolean).flat()).flat();
284
- console.log(sortedItems, 'tooltip sortedItems');
285
- const formatItems = sortedItems.map((item)=>({
286
- ...item,
287
- color: item.isCombine ? lineColors[indicators.slice(1).indexOf(String(item?.indicatorId)) ?? 0] || barColor || 'transparent' : barColor || 'transparent'
288
- }));
289
- console.log(formatItems, 'tooltip formatItems');
290
- return tooltipRender(title, formatItems ?? []) ?? null;
291
- }
292
303
  }
293
304
  });
294
305
  view.legend(false);
306
+ applyAuxiliaryLineY(view, auxiliaryLineData);
295
307
  const nodeList = [];
296
308
  console.log('nodeList data:', data);
297
309
  data.forEach((item)=>{
@@ -354,35 +366,45 @@ function renderG2CombineChart(container, options) {
354
366
  }
355
367
  });
356
368
  });
357
- if (isDataTag && formatLabel) {
358
- const groupedByX = intervalData.reduce((acc, item)=>{
359
- const key = item[x];
360
- if (!acc[key]) acc[key] = [];
361
- acc[key].push(item);
362
- return acc;
363
- }, {});
364
- const lastItemsInEachStack = new Set();
365
- Object.values(groupedByX).forEach((group)=>{
366
- group.sort((a, b)=>a[y] - b[y]);
367
- const lastItem = group[group.length - 1];
368
- lastItemsInEachStack.add(lastItem);
369
- });
370
- interval.label({
371
- dy: isGroup ? -16 : -10,
372
- dx: -10,
373
- offset: 0,
374
- text: (d)=>{
375
- if (!isGroup) return formatLabel(d);
376
- if (lastItemsInEachStack.has(d)) return formatLabel(d);
377
- return '';
378
- }
379
- });
380
- line.label({
369
+ if (formatLabel) {
370
+ if (isDataTag) {
371
+ const groupedByX = intervalData.reduce((acc, item)=>{
372
+ const key = item[x];
373
+ if (!acc[key]) acc[key] = [];
374
+ acc[key].push(item);
375
+ return acc;
376
+ }, {});
377
+ const lastItemsInEachStack = new Set();
378
+ Object.values(groupedByX).forEach((group)=>{
379
+ const lastItem = group[0];
380
+ lastItemsInEachStack.add(lastItem);
381
+ });
382
+ interval.label({
383
+ dy: -16,
384
+ dx: -10,
385
+ offset: 0,
386
+ text: (d)=>{
387
+ if (!isGroup) return formatLabel(d);
388
+ if (lastItemsInEachStack.has(d)) return formatLabel(d);
389
+ return '';
390
+ }
391
+ });
392
+ }
393
+ if (isCombineDataTag) line.label({
381
394
  dy: -10,
382
- dx: -10,
395
+ dx: 10,
383
396
  offset: 0,
384
397
  text: (d)=>formatLabel(d)
385
398
  });
399
+ view.labelTransform([
400
+ {
401
+ type: 'exceedAdjust',
402
+ bounds: 'main'
403
+ },
404
+ {
405
+ type: 'overlapHide'
406
+ }
407
+ ]);
386
408
  }
387
409
  chart.render();
388
410
  let hasEmittedNodeList = false;
@@ -19,7 +19,7 @@ function renderG2LineChart(container, options) {
19
19
  insetBottom: 0
20
20
  });
21
21
  const view = getMainView(chart);
22
- view.attr('marginBottom', isLegend ? 0 : 16);
22
+ view.attr('marginLeft', 0).attr('marginRight', 0).attr('marginBottom', isLegend ? 0 : 16);
23
23
  view.data(data);
24
24
  const domainMin = minY ?? 0;
25
25
  applyScaleYLinear(view, {
@@ -174,7 +174,11 @@ function renderG2LineChart(container, options) {
174
174
  });
175
175
  view.labelTransform([
176
176
  {
177
- type: 'overlapDodgeY'
177
+ type: 'exceedAdjust',
178
+ bounds: 'main'
179
+ },
180
+ {
181
+ type: 'overlapHide'
178
182
  }
179
183
  ]);
180
184
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@publishfx/publish-chart",
3
- "version": "2.1.3",
3
+ "version": "2.1.5",
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": [
@@ -24,20 +24,10 @@
24
24
  "CHANGELOG.md",
25
25
  "README.md"
26
26
  ],
27
- "scripts": {
28
- "build": "rslib build",
29
- "dev": "rslib build --watch",
30
- "lint": "eslint src --ext .ts,.tsx",
31
- "lint:fix": "eslint src --ext .ts,.tsx --fix",
32
- "test": "jest",
33
- "test:watch": "jest --watch",
34
- "test:coverage": "jest --coverage"
35
- },
36
27
  "devDependencies": {
37
28
  "@antv/data-set": "^0.11.8",
38
29
  "@antv/g-pattern": "^2.0.42",
39
30
  "@antv/g2": "^5.3.0",
40
- "@publishfx/publish-components": "workspace:^",
41
31
  "@types/jest": "^29.5.12",
42
32
  "@types/lodash": "^4.17.20",
43
33
  "@types/react": "^18.3.18",
@@ -55,7 +45,8 @@
55
45
  "react-dom": "^18.3.1",
56
46
  "styled-components": "^5.3.11",
57
47
  "ts-jest": "^29.1.2",
58
- "typescript": "^5.9.3"
48
+ "typescript": "^5.9.3",
49
+ "@publishfx/publish-components": "^2.1.0"
59
50
  },
60
51
  "peerDependencies": {
61
52
  "@antv/data-set": "^0.11.8",
@@ -71,5 +62,14 @@
71
62
  "publishConfig": {
72
63
  "access": "public",
73
64
  "registry": "https://registry.npmjs.org/"
65
+ },
66
+ "scripts": {
67
+ "build": "rslib build",
68
+ "dev": "rslib build --watch",
69
+ "lint": "eslint src --ext .ts,.tsx",
70
+ "lint:fix": "eslint src --ext .ts,.tsx --fix",
71
+ "test": "jest",
72
+ "test:watch": "jest --watch",
73
+ "test:coverage": "jest --coverage"
74
74
  }
75
- }
75
+ }