onesight-charts 1.4.2 → 1.4.3
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.
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
2
|
-
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
|
|
3
|
-
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
4
|
-
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
|
|
5
|
-
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
|
|
6
2
|
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
7
3
|
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
8
4
|
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
9
5
|
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
|
|
10
6
|
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
7
|
+
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
|
|
8
|
+
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
9
|
+
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
|
|
10
|
+
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
|
|
11
11
|
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
|
|
12
12
|
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
13
13
|
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
@@ -15,7 +15,7 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
|
|
|
15
15
|
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
|
|
16
16
|
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
17
17
|
import * as echarts from 'echarts';
|
|
18
|
-
import React, { useEffect, useRef, useState
|
|
18
|
+
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
|
19
19
|
import { changeDataTypeEn, computeFloat, dealBarPath, numberFormatNull } from "../../utils/chartUtils";
|
|
20
20
|
import Pagination from "../pagination";
|
|
21
21
|
import "./style.scss";
|
|
@@ -43,67 +43,28 @@ function CommonBar(props) {
|
|
|
43
43
|
callbackGetPage = _props$callbackGetPag === void 0 ? function () {} : _props$callbackGetPag,
|
|
44
44
|
_props$handleClick = props.handleClick,
|
|
45
45
|
handleClick = _props$handleClick === void 0 ? function () {} : _props$handleClick;
|
|
46
|
-
// 总数页码数
|
|
47
46
|
var _useState = useState(0),
|
|
48
47
|
_useState2 = _slicedToArray(_useState, 2),
|
|
49
48
|
total = _useState2[0],
|
|
50
49
|
setTotal = _useState2[1];
|
|
51
50
|
var chart = useRef(null);
|
|
52
|
-
// 当前页下标
|
|
53
51
|
var _useState3 = useState(1),
|
|
54
52
|
_useState4 = _slicedToArray(_useState3, 2),
|
|
55
53
|
currentPage = _useState4[0],
|
|
56
54
|
setCurrentPage = _useState4[1];
|
|
57
55
|
var chartRef = useRef(null);
|
|
58
|
-
// 存储上一次的依赖项值,用于深度比较
|
|
59
56
|
var prevDepsRef = useRef(null);
|
|
60
|
-
// 为每个组件实例生成唯一的 tooltip 类名,避免多实例冲突
|
|
61
57
|
var tooltipClassNameRef = useRef("onesight-chart-common-bar-tooltip-".concat(Date.now(), "-").concat(Math.random().toString(36).substr(2, 9)));
|
|
62
|
-
useEffect(function () {
|
|
63
|
-
// 深度比较依赖项,只有当内容真正改变时才执行
|
|
64
|
-
var currentDeps = JSON.stringify({
|
|
65
|
-
currentPage: currentPage,
|
|
66
|
-
data: data
|
|
67
|
-
});
|
|
68
|
-
var prevDeps = prevDepsRef.current;
|
|
69
|
-
|
|
70
|
-
// 如果内容没有改变,不执行
|
|
71
|
-
if (prevDeps !== null && currentDeps === prevDeps) {
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// 更新存储的值
|
|
76
|
-
prevDepsRef.current = currentDeps;
|
|
77
|
-
var copyData = JSON.parse(JSON.stringify(data));
|
|
78
|
-
var splice_data = copyData.slice((currentPage - 1) * number, currentPage * number);
|
|
79
|
-
if (data.length) {
|
|
80
|
-
setTotal(Math.ceil(data.length / number));
|
|
81
|
-
}
|
|
82
|
-
init(splice_data);
|
|
83
|
-
callbackGetPage(currentPage);
|
|
84
|
-
// 使用 setTimeout 确保 DOM 已经更新后再绑定事件
|
|
85
|
-
setTimeout(function () {
|
|
86
|
-
bindClickEvents();
|
|
87
|
-
}, 0);
|
|
88
|
-
return function () {
|
|
89
|
-
unbindClickEvents();
|
|
90
|
-
};
|
|
91
|
-
}, [currentPage, data, bindClickEvents, unbindClickEvents]);
|
|
92
58
|
var paginationCb = function paginationCb(currData, page) {
|
|
93
59
|
setCurrentPage(page);
|
|
94
60
|
};
|
|
95
61
|
var onChartClick = useCallback(function (event) {
|
|
96
|
-
// 确保只处理当前组件实例的 tooltip
|
|
97
62
|
var tooltipElement = event.target.closest(".".concat(tooltipClassNameRef.current));
|
|
98
|
-
if (!tooltipElement)
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
63
|
+
if (!tooltipElement) return;
|
|
101
64
|
var seriesNameElement = event.target.closest('.item');
|
|
102
65
|
if (seriesNameElement) {
|
|
103
66
|
var seriesItem = seriesNameElement.getAttribute('data-series-item');
|
|
104
|
-
if (!seriesItem)
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
67
|
+
if (!seriesItem) return;
|
|
107
68
|
var seriesData = JSON.parse(seriesItem);
|
|
108
69
|
handleClick && handleClick('tooltipType', seriesData);
|
|
109
70
|
}
|
|
@@ -120,6 +81,26 @@ function CommonBar(props) {
|
|
|
120
81
|
chartElement.removeEventListener('click', onChartClick);
|
|
121
82
|
}
|
|
122
83
|
}, [onChartClick]);
|
|
84
|
+
useEffect(function () {
|
|
85
|
+
var currentDeps = JSON.stringify({
|
|
86
|
+
currentPage: currentPage,
|
|
87
|
+
data: data
|
|
88
|
+
});
|
|
89
|
+
var prevDeps = prevDepsRef.current;
|
|
90
|
+
if (prevDeps !== null && currentDeps === prevDeps) return;
|
|
91
|
+
prevDepsRef.current = currentDeps;
|
|
92
|
+
var copyData = JSON.parse(JSON.stringify(data));
|
|
93
|
+
var splice_data = copyData.slice((currentPage - 1) * number, currentPage * number);
|
|
94
|
+
if (data.length) setTotal(Math.ceil(data.length / number));
|
|
95
|
+
init(splice_data);
|
|
96
|
+
callbackGetPage(currentPage);
|
|
97
|
+
setTimeout(function () {
|
|
98
|
+
bindClickEvents();
|
|
99
|
+
}, 0);
|
|
100
|
+
return function () {
|
|
101
|
+
unbindClickEvents();
|
|
102
|
+
};
|
|
103
|
+
}, [currentPage, data, bindClickEvents, unbindClickEvents, number, callbackGetPage]);
|
|
123
104
|
function toggleAxisPointer(myChart, show) {
|
|
124
105
|
myChart.setOption({
|
|
125
106
|
tooltip: {
|
|
@@ -131,49 +112,32 @@ function CommonBar(props) {
|
|
|
131
112
|
}
|
|
132
113
|
});
|
|
133
114
|
}
|
|
134
|
-
|
|
135
|
-
// 将 JSON 字符串转义为安全的 HTML 属性值
|
|
136
115
|
function escapeHtmlAttribute(jsonString) {
|
|
137
116
|
return String(jsonString).replace(/&/g, '&').replace(/"/g, '"').replace(/'/g, ''').replace(/</g, '<').replace(/>/g, '>');
|
|
138
117
|
}
|
|
139
118
|
var calculateWidth = function calculateWidth(len) {
|
|
140
|
-
if (len === 1 || len === 2 || len === 3)
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
return 24;
|
|
150
|
-
} else if (len === 8) {
|
|
151
|
-
return 20;
|
|
152
|
-
} else if (len === 9) {
|
|
153
|
-
return 18;
|
|
154
|
-
} else if (len === 10) {
|
|
155
|
-
return 16;
|
|
156
|
-
}
|
|
119
|
+
if (len === 1 || len === 2 || len === 3) return 42;
|
|
120
|
+
if (len === 4) return 40;
|
|
121
|
+
if (len === 5) return 32;
|
|
122
|
+
if (len === 6) return 26;
|
|
123
|
+
if (len === 7) return 24;
|
|
124
|
+
if (len === 8) return 20;
|
|
125
|
+
if (len === 9) return 18;
|
|
126
|
+
if (len === 10) return 16;
|
|
127
|
+
return 16;
|
|
157
128
|
};
|
|
158
129
|
function setBarData(myChart, newData) {
|
|
159
130
|
if (!myChart) return;
|
|
160
131
|
myChart.setOption({
|
|
161
|
-
series: [
|
|
162
|
-
// 背景柱(seriesIndex 0)保持不变
|
|
163
|
-
{},
|
|
164
|
-
// 前景柱(seriesIndex 1)换成新数组
|
|
165
|
-
{
|
|
132
|
+
series: [{}, {
|
|
166
133
|
data: newData
|
|
167
134
|
}]
|
|
168
|
-
}, false);
|
|
135
|
+
}, false);
|
|
169
136
|
}
|
|
170
137
|
var ICON_SIZE = 18;
|
|
171
138
|
var ICON_GAP = 0;
|
|
172
|
-
|
|
173
|
-
// 生成 y 轴富文本样式:为每一行创建 iconN,并且给 label 做截断
|
|
174
139
|
function makeYAxisRich(rows) {
|
|
175
140
|
var maxLabelWidth = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 188;
|
|
176
|
-
// 检查是否有任何行包含 platformIcon
|
|
177
141
|
var hasAnyIcon = rows.some(function (row) {
|
|
178
142
|
return row.platformIcon;
|
|
179
143
|
});
|
|
@@ -184,14 +148,10 @@ function CommonBar(props) {
|
|
|
184
148
|
fontWeight: 500,
|
|
185
149
|
lineHeight: 20,
|
|
186
150
|
align: 'right',
|
|
187
|
-
// 文本宽度 = 总宽 - 图标宽度 - 间距
|
|
188
|
-
// width: Math.max(0, maxLabelWidth - ICON_SIZE - ICON_GAP),
|
|
189
151
|
overflow: 'truncate',
|
|
190
152
|
ellipsis: '...',
|
|
191
|
-
// 如果没有任何图标,则不需要左边距
|
|
192
153
|
padding: hasAnyIcon ? [0, 0, 0, ICON_GAP] : [0, 0, 0, 0]
|
|
193
154
|
},
|
|
194
|
-
// 为没有图标的项目创建一个空的样式
|
|
195
155
|
noIcon: {
|
|
196
156
|
width: 0,
|
|
197
157
|
height: 0
|
|
@@ -204,13 +164,11 @@ function CommonBar(props) {
|
|
|
204
164
|
height: ICON_SIZE,
|
|
205
165
|
align: 'right',
|
|
206
166
|
borderRadius: 4,
|
|
207
|
-
// 这里用图片作为文本块的背景
|
|
208
167
|
backgroundColor: {
|
|
209
168
|
image: row.platformIcon
|
|
210
|
-
}
|
|
169
|
+
}
|
|
211
170
|
};
|
|
212
171
|
} else {
|
|
213
|
-
// 为没有图标的项目创建空样式
|
|
214
172
|
rich["icon".concat(i)] = {
|
|
215
173
|
width: 0,
|
|
216
174
|
height: 0
|
|
@@ -219,36 +177,20 @@ function CommonBar(props) {
|
|
|
219
177
|
});
|
|
220
178
|
return rich;
|
|
221
179
|
}
|
|
222
|
-
|
|
223
|
-
// 单行 label 的最大显示区域(和 axisLabel.width 一致)
|
|
224
180
|
var MAX_LABEL_WIDTH = 188;
|
|
225
|
-
|
|
226
|
-
// 如果该条有平台 icon,就要扣掉 icon 宽度+间距;否则直接用全部
|
|
227
181
|
function getMaxTextWidthForRow(hasIcon) {
|
|
228
182
|
return hasIcon ? MAX_LABEL_WIDTH - ICON_SIZE - ICON_GAP : MAX_LABEL_WIDTH;
|
|
229
183
|
}
|
|
230
|
-
|
|
231
|
-
// 返回一个“中间省略”的文本,尽量贴近 maxWidthPx 宽度
|
|
232
184
|
function middleEllipsis(labelText, maxWidthPx) {
|
|
233
185
|
var font = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '14px sans-serif';
|
|
234
186
|
if (!labelText) return '';
|
|
235
|
-
|
|
236
|
-
// 先测整段的宽度
|
|
237
187
|
var fullRect = echarts.format.getTextRect(labelText, font);
|
|
238
|
-
if (fullRect.width <= maxWidthPx)
|
|
239
|
-
// 不超宽,直接用原文
|
|
240
|
-
return labelText;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
// 需要省略 -> 我们要找到前半段+后半段的长度
|
|
244
|
-
// 方案:从头和尾慢慢加字符,直到超过 maxWidthPx
|
|
188
|
+
if (fullRect.width <= maxWidthPx) return labelText;
|
|
245
189
|
var DOT = '...';
|
|
246
190
|
var dotW = echarts.format.getTextRect(DOT, font).width;
|
|
247
|
-
|
|
248
|
-
// 我们会不断尝试 prefixLen / suffixLen 的组合
|
|
249
191
|
var prefixLen = 1;
|
|
250
192
|
var suffixLen = 1;
|
|
251
|
-
var best = DOT;
|
|
193
|
+
var best = DOT;
|
|
252
194
|
var bestW = dotW;
|
|
253
195
|
while (prefixLen < labelText.length && suffixLen < labelText.length) {
|
|
254
196
|
var head = labelText.slice(0, prefixLen);
|
|
@@ -256,16 +198,11 @@ function CommonBar(props) {
|
|
|
256
198
|
var candidate = head + DOT + tail;
|
|
257
199
|
var w = echarts.format.getTextRect(candidate, font).width;
|
|
258
200
|
if (w <= maxWidthPx) {
|
|
259
|
-
// 还能放得下 => 记录成当前最佳,然后再尝试加长
|
|
260
201
|
best = candidate;
|
|
261
202
|
bestW = w;
|
|
262
|
-
// 优先多给前缀,视觉更贴设计稿(你可以反过来)
|
|
263
203
|
prefixLen++;
|
|
264
|
-
if (prefixLen % 2 === 0)
|
|
265
|
-
suffixLen++;
|
|
266
|
-
}
|
|
204
|
+
if (prefixLen % 2 === 0) suffixLen++;
|
|
267
205
|
} else {
|
|
268
|
-
// 超了,就停。这个 best 就是我们要的
|
|
269
206
|
break;
|
|
270
207
|
}
|
|
271
208
|
}
|
|
@@ -282,92 +219,51 @@ function CommonBar(props) {
|
|
|
282
219
|
renderer: 'svg'
|
|
283
220
|
});
|
|
284
221
|
}
|
|
285
|
-
var fadedData = null;
|
|
222
|
+
var fadedData = null;
|
|
286
223
|
var lastIndex = null;
|
|
287
224
|
var axisData = currentData.map(function (item) {
|
|
288
225
|
return item.format || item.name || '-';
|
|
289
226
|
});
|
|
290
|
-
var
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
},
|
|
301
|
-
itemStyle: item !== null && item !== void 0 && item.proportion ? {
|
|
302
|
-
color: itemColor
|
|
303
|
-
} : {
|
|
304
|
-
color: 'rgba(29, 169, 160, 0)'
|
|
305
|
-
}
|
|
306
|
-
};
|
|
307
|
-
} else {
|
|
308
|
-
return {
|
|
309
|
-
name: item.name || '-',
|
|
310
|
-
value: item.value || 0,
|
|
311
|
-
label: {
|
|
312
|
-
// 负数就把文字放左边,正数/0 放右边
|
|
313
|
-
position: item.value < 0 ? 'left' : 'right'
|
|
314
|
-
},
|
|
315
|
-
itemStyle: item.value ? {
|
|
316
|
-
color: itemColor
|
|
317
|
-
} : {
|
|
318
|
-
color: 'rgba(29, 169, 160, 0)'
|
|
319
|
-
}
|
|
320
|
-
};
|
|
321
|
-
}
|
|
322
|
-
});
|
|
323
|
-
var originalData = seriesData.map(function (d) {
|
|
324
|
-
return _objectSpread(_objectSpread({}, d), {}, {
|
|
325
|
-
itemStyle: _objectSpread(_objectSpread({}, d.itemStyle || {}), {}, {
|
|
326
|
-
opacity: 1
|
|
327
|
-
})
|
|
328
|
-
});
|
|
329
|
-
});
|
|
330
|
-
var maxDataValue = Math.max.apply(Math, _toConsumableArray(currentData.map(function (item) {
|
|
331
|
-
return showProportion ? item === null || item === void 0 ? void 0 : item.proportion : item.value;
|
|
332
|
-
})));
|
|
333
|
-
// ① 先测出 Y 轴中最长的类目文本宽度
|
|
227
|
+
var yIconFlag = data === null || data === void 0 || (_data$ = data[0]) === null || _data$ === void 0 ? void 0 : _data$.platformIcon;
|
|
228
|
+
var valueAccessor = function valueAccessor(item) {
|
|
229
|
+
return showProportion ? (item === null || item === void 0 ? void 0 : item.proportion) || 0 : item.value || 0;
|
|
230
|
+
};
|
|
231
|
+
var maxDataValue = Math.max.apply(Math, _toConsumableArray(currentData.map(valueAccessor)));
|
|
232
|
+
var minDataValue = Math.min.apply(Math, _toConsumableArray(currentData.map(valueAccessor)));
|
|
233
|
+
var hasNegative = minDataValue < 0;
|
|
234
|
+
var allNegative = maxDataValue < 0;
|
|
235
|
+
|
|
236
|
+
// === 计算 barAreaWidth(用于换算像素)===
|
|
334
237
|
var ySample = axisData.reduce(function (a, b) {
|
|
335
238
|
return a.length > b.length ? a : b;
|
|
336
239
|
}, '');
|
|
337
240
|
var yLabelWidth = echarts.format.getTextRect(ySample, '14px sans-serif').width;
|
|
338
|
-
// 你在 axisLabel 里写了 margin: 10
|
|
339
241
|
var axisLabelGap = 10;
|
|
340
242
|
var chartWidth = myChart.getWidth();
|
|
341
243
|
var leftPadding = 12;
|
|
342
244
|
var rightPadding = 0;
|
|
343
245
|
var gridWidth = chartWidth - leftPadding - rightPadding;
|
|
344
246
|
var dealYLabelWidth = yLabelWidth > 188 ? 188 : yLabelWidth;
|
|
345
|
-
// ③ 真正柱子可用的像素宽度
|
|
346
247
|
var barAreaWidth = gridWidth - dealYLabelWidth - axisLabelGap;
|
|
248
|
+
|
|
249
|
+
// 正数端 bgValue(你的原逻辑保留)
|
|
347
250
|
var sampleText = showProportion ? computeFloat(maxDataValue) : numberFormatNull(maxDataValue);
|
|
348
251
|
var labelWidth = echarts.format.getTextRect(sampleText, '14px sans-serif').width;
|
|
349
|
-
var
|
|
350
|
-
var
|
|
351
|
-
var
|
|
352
|
-
return showProportion ? (item === null || item === void 0 ? void 0 : item.proportion) || 0 : item.value || 0;
|
|
353
|
-
};
|
|
354
|
-
var minDataValue = Math.min.apply(Math, _toConsumableArray(currentData.map(valueAccessor)));
|
|
355
|
-
var hasNegative = minDataValue < 0;
|
|
356
|
-
var allNegative = maxDataValue < 0; // 检查是否所有数据都是负数
|
|
357
|
-
|
|
252
|
+
var LABEL_DISTANCE = 5; // 要和 series.label.distance 保持一致
|
|
253
|
+
var SAFE_PX = 12; // 额外保险像素,避免误差导致溢出
|
|
254
|
+
var extra = 15 + LABEL_DISTANCE + SAFE_PX;
|
|
358
255
|
var bgValue;
|
|
359
|
-
// 如果所有数据都是负数,bgValue 应该设置为 0,让 xAxis.max 至少是 0
|
|
360
256
|
if (allNegative) {
|
|
361
257
|
bgValue = 0;
|
|
362
258
|
} else if (barAreaWidth > labelWidth + extra) {
|
|
363
259
|
bgValue = maxDataValue * barAreaWidth / (barAreaWidth - labelWidth - extra);
|
|
364
260
|
} else {
|
|
365
|
-
var overflowPx = labelWidth + extra - barAreaWidth;
|
|
366
|
-
var unitPerPx = maxDataValue / barAreaWidth
|
|
367
|
-
bgValue = maxDataValue + overflowPx * unitPerPx;
|
|
261
|
+
var overflowPx = labelWidth + extra - barAreaWidth;
|
|
262
|
+
var unitPerPx = maxDataValue / Math.max(barAreaWidth, 1);
|
|
263
|
+
bgValue = maxDataValue + overflowPx * unitPerPx;
|
|
368
264
|
}
|
|
369
265
|
|
|
370
|
-
//
|
|
266
|
+
// 负数端 minBgValue(你的原逻辑保留)
|
|
371
267
|
var minBgValue = 0;
|
|
372
268
|
if (hasNegative) {
|
|
373
269
|
var absMinDataValue = Math.abs(minDataValue);
|
|
@@ -375,21 +271,14 @@ function CommonBar(props) {
|
|
|
375
271
|
var minLabelSample = showProportion ? computeFloat(absMinDataValue) : numberFormatNull(absMinDataValue);
|
|
376
272
|
var minLabelWidth = echarts.format.getTextRect(minLabelSample, '14px sans-serif').width;
|
|
377
273
|
var minExtra = 15;
|
|
378
|
-
|
|
379
|
-
// 计算整个x轴的数据范围(从最小负数到最大正数)
|
|
380
274
|
var totalDataRange = absMinDataValue + absMaxDataValue;
|
|
381
|
-
|
|
382
|
-
// 计算负数部分应该占用的像素宽度
|
|
383
275
|
var negativeBarAreaWidth;
|
|
384
|
-
// 如果所有数据都是负数,使用整个 barAreaWidth 来显示负数
|
|
385
276
|
if (allNegative) {
|
|
386
277
|
negativeBarAreaWidth = barAreaWidth;
|
|
387
278
|
} else if (totalDataRange > 0) {
|
|
388
279
|
if (absMinDataValue < absMaxDataValue * 0.3) {
|
|
389
|
-
// 负数很小,只给必要的空间(标签宽度 + 一些余量)
|
|
390
280
|
negativeBarAreaWidth = Math.min(minLabelWidth + minExtra + 30, barAreaWidth * 0.25);
|
|
391
281
|
} else {
|
|
392
|
-
// 按比例分配,但确保至少能显示标签
|
|
393
282
|
var ratio = absMinDataValue / totalDataRange;
|
|
394
283
|
negativeBarAreaWidth = barAreaWidth * ratio;
|
|
395
284
|
negativeBarAreaWidth = Math.max(negativeBarAreaWidth, minLabelWidth + minExtra + 20);
|
|
@@ -397,18 +286,10 @@ function CommonBar(props) {
|
|
|
397
286
|
} else {
|
|
398
287
|
negativeBarAreaWidth = barAreaWidth * 0.5;
|
|
399
288
|
}
|
|
400
|
-
|
|
401
|
-
// 计算 minBgValue:让负数柱子尽可能紧凑,只留出标签空间
|
|
402
|
-
// 负数柱子占用的像素 = negativeBarAreaWidth - minLabelWidth - minExtra
|
|
403
289
|
var availableBarWidth = Math.max(1, negativeBarAreaWidth - minLabelWidth - minExtra);
|
|
404
|
-
// 计算每像素对应的数据值
|
|
405
290
|
var dataPerPixel = absMinDataValue / availableBarWidth;
|
|
406
|
-
|
|
407
|
-
var labelSpaceInData = (minLabelWidth + minExtra) * dataPerPixel;
|
|
291
|
+
var labelSpaceInData = (minLabelWidth + minExtra) * dataPerPixel * 1.3;
|
|
408
292
|
minBgValue = -(absMinDataValue + labelSpaceInData);
|
|
409
|
-
|
|
410
|
-
// 如果同时有正数,重新计算正数的 bgValue,使用剩余空间
|
|
411
|
-
// 如果所有数据都是负数,bgValue 保持为 0
|
|
412
293
|
if (maxDataValue > 0 && !allNegative) {
|
|
413
294
|
var positiveBarAreaWidth = barAreaWidth - negativeBarAreaWidth;
|
|
414
295
|
if (positiveBarAreaWidth > labelWidth + extra) {
|
|
@@ -420,14 +301,53 @@ function CommonBar(props) {
|
|
|
420
301
|
}
|
|
421
302
|
}
|
|
422
303
|
}
|
|
304
|
+
|
|
305
|
+
// ====== 方案B:把“小值”钳到至少 4px,但展示仍用真实值 ======
|
|
306
|
+
var MIN_BAR_PX = 4;
|
|
307
|
+
var safeBarAreaWidth = Math.max(1, barAreaWidth);
|
|
308
|
+
var axisSpan = bgValue - minBgValue;
|
|
309
|
+
axisSpan = Math.max(axisSpan, 1);
|
|
310
|
+
var minVisibleValue = axisSpan * (MIN_BAR_PX / safeBarAreaWidth);
|
|
311
|
+
minVisibleValue = Math.max(minVisibleValue, 1);
|
|
312
|
+
|
|
313
|
+
// 确保 xAxis.min 能容纳钳制后的负值长度,否则仍会被裁剪
|
|
314
|
+
if (hasNegative) {
|
|
315
|
+
minBgValue = Math.min(minBgValue, -minVisibleValue * 1.1);
|
|
316
|
+
axisSpan = Math.max(bgValue - minBgValue, 1);
|
|
317
|
+
minVisibleValue = Math.max(axisSpan * (MIN_BAR_PX / safeBarAreaWidth), 1);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// 前景 seriesData:保存 rawValue(真实值),value 用于绘制(钳制)
|
|
321
|
+
var seriesData = currentData.map(function (item) {
|
|
322
|
+
var itemColor = item.color || barColor;
|
|
323
|
+
var raw = valueAccessor(item);
|
|
324
|
+
var displayValue = raw === 0 ? 0 : Math.sign(raw) * Math.max(Math.abs(raw), minVisibleValue);
|
|
325
|
+
return {
|
|
326
|
+
name: item.name || '-',
|
|
327
|
+
rawValue: raw,
|
|
328
|
+
value: displayValue,
|
|
329
|
+
label: {
|
|
330
|
+
position: raw < 0 ? 'left' : 'right'
|
|
331
|
+
},
|
|
332
|
+
itemStyle: raw ? {
|
|
333
|
+
color: itemColor
|
|
334
|
+
} : {
|
|
335
|
+
color: 'rgba(29, 169, 160, 0)'
|
|
336
|
+
}
|
|
337
|
+
};
|
|
338
|
+
});
|
|
339
|
+
var originalData = seriesData.map(function (d) {
|
|
340
|
+
return _objectSpread(_objectSpread({}, d), {}, {
|
|
341
|
+
itemStyle: _objectSpread(_objectSpread({}, d.itemStyle || {}), {}, {
|
|
342
|
+
opacity: 1
|
|
343
|
+
})
|
|
344
|
+
});
|
|
345
|
+
});
|
|
423
346
|
var option = {
|
|
424
347
|
tooltip: {
|
|
425
348
|
className: "onesight-chart-common-bar-tooltip ".concat(tooltipClassNameRef.current),
|
|
426
349
|
trigger: 'axis',
|
|
427
350
|
enterable: true,
|
|
428
|
-
// showContent: true,
|
|
429
|
-
// alwaysShowContent: true,
|
|
430
|
-
// hideDelay: 1000000000,
|
|
431
351
|
padding: 0,
|
|
432
352
|
position: function position(point, params, dom) {
|
|
433
353
|
var tooltipHeight = (dom === null || dom === void 0 ? void 0 : dom.offsetHeight) || 0;
|
|
@@ -452,26 +372,24 @@ function CommonBar(props) {
|
|
|
452
372
|
var _res$, _res$2;
|
|
453
373
|
if (!res.some(function (i) {
|
|
454
374
|
return i.value !== undefined && i.value !== null;
|
|
455
|
-
}))
|
|
456
|
-
return '';
|
|
457
|
-
}
|
|
375
|
+
})) return '';
|
|
458
376
|
var dataArr = [res[1]];
|
|
459
377
|
var currentColor = ((_res$ = res[1]) === null || _res$ === void 0 ? void 0 : _res$.color) || '#1DA9A0';
|
|
460
378
|
var triangleWidth = 280;
|
|
461
|
-
// 获取当前数据项的索引,以便从 currentData 中获取 alias
|
|
462
379
|
var dataIndex = (_res$2 = res[1]) === null || _res$2 === void 0 ? void 0 : _res$2.dataIndex;
|
|
463
380
|
var originalItem = currentData[dataIndex];
|
|
464
|
-
return "<div class='onesight-chart-common-bar-tooltip-box' style=\"width:278px;position: relative;\">\n
|
|
465
|
-
|
|
381
|
+
return "<div class='onesight-chart-common-bar-tooltip-box' style=\"width:278px;position: relative;\">\n ".concat(isTooltipTitleShow ? "<div class=\"tooltip-head\">".concat(res[0].format || res[0].name, "</div>") : '', "\n <div class='tooltip-body'>\n ").concat(dataArr.map(function (item) {
|
|
382
|
+
var _item$data;
|
|
383
|
+
var raw = (item === null || item === void 0 || (_item$data = item.data) === null || _item$data === void 0 ? void 0 : _item$data.rawValue) !== undefined ? item.data.rawValue : item.value;
|
|
466
384
|
var itemWithAlias = _objectSpread(_objectSpread({}, item), {}, {
|
|
467
385
|
alias: originalItem === null || originalItem === void 0 ? void 0 : originalItem.alias,
|
|
468
386
|
alias2: originalItem === null || originalItem === void 0 ? void 0 : originalItem.alias2,
|
|
469
|
-
aliasArray: originalItem === null || originalItem === void 0 ? void 0 : originalItem.aliasArray
|
|
387
|
+
aliasArray: originalItem === null || originalItem === void 0 ? void 0 : originalItem.aliasArray,
|
|
388
|
+
rawValue: raw
|
|
470
389
|
});
|
|
471
|
-
// 将 JSON 字符串转义为安全的 HTML 属性值
|
|
472
390
|
var escapedJson = escapeHtmlAttribute(JSON.stringify(itemWithAlias));
|
|
473
|
-
return "<div class='item' data-series-item=\"".concat(escapedJson, "\" key='").concat(item.seriesName, "'>\n
|
|
474
|
-
}).join(''), "\n
|
|
391
|
+
return "<div class='item' data-series-item=\"".concat(escapedJson, "\" key='").concat(item.seriesName, "'>\n <div class='l'>\n <span style=\"display:inline-block;width: 14px;vertical-align: middle;height: 14px;background-color:").concat(currentColor, ";border-radius: 4px;margin-bottom: 2px;margin-right:6px\"></span>\n <span>").concat(tooltipItemName ? res[0].format || res[0].name : tipName, "</span>\n </div>\n <div class='r' style=\"padding-left:6px;\">\n <span class='num'>").concat(showProportion ? computeFloat(raw) : changeDataTypeEn(raw), "</span>\n </div>\n </div>");
|
|
392
|
+
}).join(''), "\n </div>\n <div class='triangle-down' style='width:").concat(triangleWidth, "px'></div>\n </div>");
|
|
475
393
|
}
|
|
476
394
|
},
|
|
477
395
|
animation: true,
|
|
@@ -482,16 +400,15 @@ function CommonBar(props) {
|
|
|
482
400
|
},
|
|
483
401
|
grid: {
|
|
484
402
|
top: 0,
|
|
485
|
-
// bottom: 30,
|
|
486
403
|
bottom: 0,
|
|
487
404
|
left: 12,
|
|
488
|
-
right:
|
|
405
|
+
right: 0,
|
|
489
406
|
containLabel: true
|
|
490
407
|
},
|
|
491
408
|
xAxis: {
|
|
492
409
|
type: 'value',
|
|
493
410
|
max: bgValue,
|
|
494
|
-
min:
|
|
411
|
+
min: minBgValue,
|
|
495
412
|
show: false,
|
|
496
413
|
axisLine: {
|
|
497
414
|
show: false
|
|
@@ -516,30 +433,13 @@ function CommonBar(props) {
|
|
|
516
433
|
show: true,
|
|
517
434
|
interval: 0,
|
|
518
435
|
rotate: 0,
|
|
519
|
-
// width: 188,
|
|
520
436
|
overflow: 'truncate',
|
|
521
437
|
ellipsis: '...',
|
|
522
|
-
// formatter: function (value, index) {
|
|
523
|
-
// // 检查当前项是否有 platformIcon
|
|
524
|
-
// if (yIconFlag) {
|
|
525
|
-
// return `{icon${index}|} {label|${value}}`;
|
|
526
|
-
// } else {
|
|
527
|
-
// return value;
|
|
528
|
-
// }
|
|
529
|
-
// },
|
|
530
438
|
formatter: function formatter(value, index) {
|
|
531
439
|
var _currentData$index;
|
|
532
|
-
// 这一行有没有图标?
|
|
533
440
|
var rowHasIcon = !!(yIconFlag && (_currentData$index = currentData[index]) !== null && _currentData$index !== void 0 && _currentData$index.platformIcon);
|
|
534
|
-
|
|
535
|
-
// 这一行文本可用的最大宽度(扣除图标)
|
|
536
441
|
var maxPx = getMaxTextWidthForRow(rowHasIcon);
|
|
537
|
-
|
|
538
|
-
// 得到“中间省略版”文本
|
|
539
|
-
var finalText = middleEllipsis(value, maxPx, '14px sans-serif' // 跟 axisLabel 字体保持一致
|
|
540
|
-
);
|
|
541
|
-
|
|
542
|
-
// 按是否有 icon,返回富文本还是普通文本
|
|
442
|
+
var finalText = middleEllipsis(value, maxPx, '14px sans-serif');
|
|
543
443
|
if (yIconFlag) {
|
|
544
444
|
return "{icon".concat(index, "|} {label|").concat(finalText, "}");
|
|
545
445
|
} else {
|
|
@@ -559,52 +459,40 @@ function CommonBar(props) {
|
|
|
559
459
|
data: axisData
|
|
560
460
|
},
|
|
561
461
|
series: [{
|
|
562
|
-
// === 背景柱系列 ===
|
|
563
|
-
// 需要背景柱的原因是让柱状条加上后面的数字标签的和不超过悬浮上去的阴影的长度
|
|
564
462
|
name: '背景条',
|
|
565
463
|
type: 'bar',
|
|
566
|
-
// 让它在最底层
|
|
567
464
|
z: 1,
|
|
568
|
-
// 不需要点击/hover 交互
|
|
569
465
|
silent: true,
|
|
570
|
-
// 让柱子和后面的柱子重叠在同一个类目位置
|
|
571
466
|
barGap: '-100%',
|
|
572
467
|
emphasis: {
|
|
573
468
|
disabled: true
|
|
574
469
|
},
|
|
575
|
-
// 柱子的样式
|
|
576
470
|
itemStyle: {
|
|
577
|
-
color: 'rgba(0, 0, 0, 0)'
|
|
471
|
+
color: 'rgba(0, 0, 0, 0)'
|
|
578
472
|
},
|
|
579
|
-
// 这里的 data 根据正负数使用不同的背景值
|
|
580
473
|
data: currentData.map(function (item) {
|
|
581
|
-
var
|
|
582
|
-
return
|
|
474
|
+
var v = valueAccessor(item);
|
|
475
|
+
return v < 0 ? minBgValue : bgValue;
|
|
583
476
|
}),
|
|
584
|
-
// 根据你需要的柱宽
|
|
585
|
-
// barMaxWidth: 42,
|
|
586
|
-
// barMinWidth: 16,
|
|
587
477
|
barWidth: calculateWidth(seriesData.length),
|
|
478
|
+
// 这里留着也无所谓,但“最小可见长度”由方案B控制
|
|
588
479
|
barMinHeight: 4,
|
|
480
|
+
barMinWidth: 4,
|
|
589
481
|
cursor: 'pointer',
|
|
590
482
|
animation: false,
|
|
591
|
-
showBackground: false
|
|
483
|
+
showBackground: false
|
|
592
484
|
}, {
|
|
593
485
|
type: 'bar',
|
|
594
|
-
// showBackground: true,
|
|
595
486
|
label: {
|
|
596
487
|
show: true,
|
|
597
|
-
// position: 'right',
|
|
598
488
|
fontWeight: 400,
|
|
599
489
|
fontSize: 14,
|
|
600
490
|
color: '#515E5F',
|
|
601
491
|
distance: 5,
|
|
602
492
|
formatter: function formatter(params) {
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
return numberFormatNull(params.value);
|
|
607
|
-
}
|
|
493
|
+
var _params$data$rawValue, _params$data;
|
|
494
|
+
var raw = (_params$data$rawValue = params === null || params === void 0 || (_params$data = params.data) === null || _params$data === void 0 ? void 0 : _params$data.rawValue) !== null && _params$data$rawValue !== void 0 ? _params$data$rawValue : params.value;
|
|
495
|
+
return showProportion ? computeFloat(raw) : numberFormatNull(raw);
|
|
608
496
|
}
|
|
609
497
|
},
|
|
610
498
|
emphasis: {
|
|
@@ -615,10 +503,9 @@ function CommonBar(props) {
|
|
|
615
503
|
borderWidth: 0,
|
|
616
504
|
borderType: 'solid'
|
|
617
505
|
},
|
|
618
|
-
// barMaxWidth: 42,
|
|
619
|
-
// barMinWidth: 16,
|
|
620
506
|
barWidth: calculateWidth(seriesData.length),
|
|
621
507
|
barMinHeight: 4,
|
|
508
|
+
barMinWidth: 4,
|
|
622
509
|
cursor: 'pointer',
|
|
623
510
|
animation: false,
|
|
624
511
|
data: seriesData
|
|
@@ -661,9 +548,7 @@ function CommonBar(props) {
|
|
|
661
548
|
});
|
|
662
549
|
myChart.on('showTip', function (_ref) {
|
|
663
550
|
var dataIndex = _ref.dataIndex;
|
|
664
|
-
// 鼠标微移时不重复更新
|
|
665
551
|
if (dataIndex === lastIndex) return;
|
|
666
|
-
// 生成淡化后的数组(只改非当前柱)
|
|
667
552
|
fadedData = originalData.map(function (d, i) {
|
|
668
553
|
return _objectSpread(_objectSpread({}, d), {}, {
|
|
669
554
|
itemStyle: _objectSpread(_objectSpread({}, d.itemStyle || {}), {}, {
|
|
@@ -677,7 +562,6 @@ function CommonBar(props) {
|
|
|
677
562
|
});
|
|
678
563
|
myChart.on('hideTip', function () {
|
|
679
564
|
if (lastIndex === null) return;
|
|
680
|
-
// 恢复全部不透明
|
|
681
565
|
setBarData(myChart, originalData);
|
|
682
566
|
toggleAxisPointer(myChart, false);
|
|
683
567
|
lastIndex = null;
|
|
@@ -692,7 +576,6 @@ function CommonBar(props) {
|
|
|
692
576
|
element.addEventListener('mouseleave', function (event) {
|
|
693
577
|
if (event && element.offsetHeight && event.offsetY < element.offsetHeight - 2) {
|
|
694
578
|
if (lastIndex === null) return;
|
|
695
|
-
// 恢复全部不透明
|
|
696
579
|
setBarData(myChart, originalData);
|
|
697
580
|
myChart.dispatchAction({
|
|
698
581
|
type: 'hideTip'
|