@yoka-ui/ui 1.0.6 → 1.0.7
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/@Docs-yoka/exports.generated.md +3 -3
- package/README.md +6 -6
- package/dist/es/assets/image/skills.zip +0 -0
- package/dist/es/business/Empty/index.js.map +1 -1
- package/dist/es/business/YkCharts/Area.d.ts +18 -0
- package/dist/es/business/YkCharts/Area.js +336 -0
- package/dist/es/business/YkCharts/Area.js.map +7 -0
- package/dist/es/business/YkCharts/Bar.d.ts +21 -0
- package/dist/es/business/YkCharts/Bar.js +316 -0
- package/dist/es/business/YkCharts/Bar.js.map +7 -0
- package/dist/es/business/YkCharts/BarProperty.d.ts +21 -0
- package/dist/es/business/YkCharts/BarProperty.js +357 -0
- package/dist/es/business/YkCharts/BarProperty.js.map +7 -0
- package/dist/es/business/YkCharts/BarTotal.d.ts +21 -0
- package/dist/es/business/YkCharts/BarTotal.js +288 -0
- package/dist/es/business/YkCharts/BarTotal.js.map +7 -0
- package/dist/es/business/YkCharts/Line.d.ts +21 -0
- package/dist/es/business/YkCharts/Line.js +342 -0
- package/dist/es/business/YkCharts/Line.js.map +7 -0
- package/dist/es/business/YkCharts/Pie.d.ts +19 -0
- package/dist/es/business/YkCharts/Pie.js +107 -0
- package/dist/es/business/YkCharts/Pie.js.map +7 -0
- package/dist/es/business/YkCharts/PieProperty.d.ts +18 -0
- package/dist/es/business/YkCharts/PieProperty.js +180 -0
- package/dist/es/business/YkCharts/PieProperty.js.map +7 -0
- package/dist/es/business/YkCharts/Pies.d.ts +26 -0
- package/dist/es/business/YkCharts/Pies.js +348 -0
- package/dist/es/business/YkCharts/Pies.js.map +7 -0
- package/dist/es/business/YkCharts/constants.d.ts +1 -0
- package/dist/es/business/YkCharts/constants.js +47 -0
- package/dist/es/business/YkCharts/constants.js.map +7 -0
- package/dist/es/business/YkCharts/hooks.d.ts +4 -0
- package/dist/es/business/YkCharts/hooks.js +37 -0
- package/dist/es/business/YkCharts/hooks.js.map +7 -0
- package/dist/es/business/YkCharts/index.d.ts +9 -0
- package/dist/es/business/YkCharts/index.js +20 -0
- package/dist/es/business/YkCharts/index.js.map +7 -0
- package/dist/es/business/YkCharts/index.module.less +164 -0
- package/dist/es/business/YkCharts/tooltip.less +92 -0
- package/dist/es/business/YkCharts/transformData.js +16 -0
- package/dist/es/business/YkCharts/transformData.js.map +7 -0
- package/dist/es/business/YkCharts/typing.d.ts +74 -0
- package/dist/es/business/YkCharts/typing.js +1 -0
- package/dist/es/business/YkCharts/typing.js.map +7 -0
- package/dist/es/business/YkCharts/utils.d.ts +4 -0
- package/dist/es/business/YkCharts/utils.js +109 -0
- package/dist/es/business/YkCharts/utils.js.map +7 -0
- package/dist/es/business/YkCharts/variables.less +13 -0
- package/dist/es/components/YKMarkdown/index.d.ts +11 -0
- package/dist/es/components/YKMarkdown/index.js +236 -0
- package/dist/es/components/YKMarkdown/index.js.map +7 -0
- package/dist/es/components/YKMarkdown/index.module.less +83 -0
- package/dist/es/components/YkDateRangePicker/YkDateRangePicker.mdx +3 -3
- package/dist/es/creative/GlassSegmentedRadio/index.d.ts +1 -1
- package/dist/es/creative/SkillsWriter/index.d.ts +3 -0
- package/dist/es/creative/SkillsWriter/index.js +191 -0
- package/dist/es/creative/SkillsWriter/index.js.map +7 -0
- package/dist/es/creative/SkillsWriter/index.module.less +21 -0
- package/dist/es/index.less +6 -1
- package/dist/es/utils/ykStorybookDoc.d.ts +15 -0
- package/dist/es/utils/ykStorybookDoc.js +24 -2
- package/dist/es/utils/ykStorybookDoc.js.map +2 -2
- package/dist/lib/assets/image/skills.zip +0 -0
- package/dist/lib/business/Empty/index.js.map +1 -1
- package/dist/lib/business/YkCharts/Area.d.ts +18 -0
- package/dist/lib/business/YkCharts/Area.js +346 -0
- package/dist/lib/business/YkCharts/Area.js.map +7 -0
- package/dist/lib/business/YkCharts/Bar.d.ts +21 -0
- package/dist/lib/business/YkCharts/Bar.js +323 -0
- package/dist/lib/business/YkCharts/Bar.js.map +7 -0
- package/dist/lib/business/YkCharts/BarProperty.d.ts +21 -0
- package/dist/lib/business/YkCharts/BarProperty.js +370 -0
- package/dist/lib/business/YkCharts/BarProperty.js.map +7 -0
- package/dist/lib/business/YkCharts/BarTotal.d.ts +21 -0
- package/dist/lib/business/YkCharts/BarTotal.js +295 -0
- package/dist/lib/business/YkCharts/BarTotal.js.map +7 -0
- package/dist/lib/business/YkCharts/Line.d.ts +21 -0
- package/dist/lib/business/YkCharts/Line.js +349 -0
- package/dist/lib/business/YkCharts/Line.js.map +7 -0
- package/dist/lib/business/YkCharts/Pie.d.ts +19 -0
- package/dist/lib/business/YkCharts/Pie.js +117 -0
- package/dist/lib/business/YkCharts/Pie.js.map +7 -0
- package/dist/lib/business/YkCharts/PieProperty.d.ts +18 -0
- package/dist/lib/business/YkCharts/PieProperty.js +193 -0
- package/dist/lib/business/YkCharts/PieProperty.js.map +7 -0
- package/dist/lib/business/YkCharts/Pies.d.ts +26 -0
- package/dist/lib/business/YkCharts/Pies.js +337 -0
- package/dist/lib/business/YkCharts/Pies.js.map +7 -0
- package/dist/lib/business/YkCharts/constants.d.ts +1 -0
- package/dist/lib/business/YkCharts/constants.js +71 -0
- package/dist/lib/business/YkCharts/constants.js.map +7 -0
- package/dist/lib/business/YkCharts/hooks.d.ts +4 -0
- package/dist/lib/business/YkCharts/hooks.js +62 -0
- package/dist/lib/business/YkCharts/hooks.js.map +7 -0
- package/dist/lib/business/YkCharts/index.d.ts +9 -0
- package/dist/lib/business/YkCharts/index.js +61 -0
- package/dist/lib/business/YkCharts/index.js.map +7 -0
- package/dist/lib/business/YkCharts/index.module.less +164 -0
- package/dist/lib/business/YkCharts/tooltip.less +92 -0
- package/dist/lib/business/YkCharts/transformData.js +40 -0
- package/dist/lib/business/YkCharts/transformData.js.map +7 -0
- package/dist/lib/business/YkCharts/typing.d.ts +74 -0
- package/dist/lib/business/YkCharts/typing.js +18 -0
- package/dist/lib/business/YkCharts/typing.js.map +7 -0
- package/dist/lib/business/YkCharts/utils.d.ts +4 -0
- package/dist/lib/business/YkCharts/utils.js +143 -0
- package/dist/lib/business/YkCharts/utils.js.map +7 -0
- package/dist/lib/business/YkCharts/variables.less +13 -0
- package/dist/lib/components/YKMarkdown/index.d.ts +11 -0
- package/dist/lib/components/YKMarkdown/index.js +188 -0
- package/dist/lib/components/YKMarkdown/index.js.map +7 -0
- package/dist/lib/components/YKMarkdown/index.module.less +83 -0
- package/dist/lib/components/YkDateRangePicker/YkDateRangePicker.mdx +3 -3
- package/dist/lib/creative/GlassSegmentedRadio/index.d.ts +1 -1
- package/dist/lib/creative/SkillsWriter/index.d.ts +3 -0
- package/dist/lib/creative/SkillsWriter/index.js +200 -0
- package/dist/lib/creative/SkillsWriter/index.js.map +7 -0
- package/dist/lib/creative/SkillsWriter/index.module.less +21 -0
- package/dist/lib/index.less +6 -1
- package/dist/lib/utils/ykStorybookDoc.d.ts +15 -0
- package/dist/lib/utils/ykStorybookDoc.js +23 -1
- package/dist/lib/utils/ykStorybookDoc.js.map +2 -2
- package/package.json +152 -143
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defProps = Object.defineProperties;
|
|
3
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
7
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8
|
+
var __spreadValues = (a, b) => {
|
|
9
|
+
for (var prop in b || (b = {}))
|
|
10
|
+
if (__hasOwnProp.call(b, prop))
|
|
11
|
+
__defNormalProp(a, prop, b[prop]);
|
|
12
|
+
if (__getOwnPropSymbols)
|
|
13
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
14
|
+
if (__propIsEnum.call(b, prop))
|
|
15
|
+
__defNormalProp(a, prop, b[prop]);
|
|
16
|
+
}
|
|
17
|
+
return a;
|
|
18
|
+
};
|
|
19
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
|
+
|
|
21
|
+
// src/business/YkCharts/BarTotal.tsx
|
|
22
|
+
import { Empty, message } from "antd";
|
|
23
|
+
import classNames from "classnames";
|
|
24
|
+
import Decimal from "decimal.js";
|
|
25
|
+
import * as echarts from "echarts";
|
|
26
|
+
import React, { useEffect, useMemo, useRef } from "react";
|
|
27
|
+
import ReactDOMServer from "react-dom/server";
|
|
28
|
+
import { chartColors } from "./constants";
|
|
29
|
+
import styles from "./index.module.less";
|
|
30
|
+
import { formatNumber, formatValue } from "./utils";
|
|
31
|
+
var MAX_SECTORS = 500;
|
|
32
|
+
var BarTotal = ({
|
|
33
|
+
count,
|
|
34
|
+
// 指标显示数量
|
|
35
|
+
metric,
|
|
36
|
+
// 指标
|
|
37
|
+
groupBys,
|
|
38
|
+
// 维度
|
|
39
|
+
tableData,
|
|
40
|
+
// 表格数据
|
|
41
|
+
baseData,
|
|
42
|
+
// 基础数据
|
|
43
|
+
columnConfigMap,
|
|
44
|
+
// 列配置
|
|
45
|
+
height
|
|
46
|
+
}) => {
|
|
47
|
+
const chartContainerRef = useRef(null);
|
|
48
|
+
const chartInstanceRef = useRef(null);
|
|
49
|
+
const validGroupByKeys = useMemo(() => {
|
|
50
|
+
return groupBys.filter((g) => Array.isArray(g.selected) && g.selected.length > 0).map((g) => g.key);
|
|
51
|
+
}, [groupBys]);
|
|
52
|
+
const seriesData = useMemo(() => {
|
|
53
|
+
if (Array.isArray(groupBys) && groupBys.some((g) => Array.isArray(g.selected) && g.selected.length === 0)) {
|
|
54
|
+
return [];
|
|
55
|
+
}
|
|
56
|
+
const validGroupBys = groupBys.filter((g) => Array.isArray(g.selected) && g.selected.length > 0);
|
|
57
|
+
if (!baseData || baseData.length === 0) {
|
|
58
|
+
return [];
|
|
59
|
+
}
|
|
60
|
+
const filteredBaseData = baseData.filter((item) => {
|
|
61
|
+
return validGroupBys.every((g) => {
|
|
62
|
+
var _a;
|
|
63
|
+
const itemValue = String((_a = item[g.key]) != null ? _a : "");
|
|
64
|
+
return g.selected.includes(itemValue);
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
const byGroupBy = /* @__PURE__ */ new Map();
|
|
68
|
+
filteredBaseData.forEach((item) => {
|
|
69
|
+
const groupByValues = validGroupByKeys.map((key) => {
|
|
70
|
+
var _a;
|
|
71
|
+
return String((_a = item[key]) != null ? _a : "");
|
|
72
|
+
}).join("|");
|
|
73
|
+
const name = validGroupByKeys.map((key) => item[key]).join(",");
|
|
74
|
+
if (!byGroupBy.has(groupByValues)) {
|
|
75
|
+
byGroupBy.set(groupByValues, { name, rows: [] });
|
|
76
|
+
}
|
|
77
|
+
byGroupBy.get(groupByValues).rows.push(item);
|
|
78
|
+
});
|
|
79
|
+
const result = Array.from(byGroupBy.entries()).map(([, { name, rows }]) => {
|
|
80
|
+
const data = metric.map((m) => {
|
|
81
|
+
const sum = rows.reduce((s, r) => s + (Number(r[m]) || 0), 0);
|
|
82
|
+
return sum;
|
|
83
|
+
});
|
|
84
|
+
const dataSum = data.reduce((s, v) => s + (isNaN(v) ? 0 : v), 0);
|
|
85
|
+
return {
|
|
86
|
+
name,
|
|
87
|
+
type: "bar",
|
|
88
|
+
barMaxWidth: 20,
|
|
89
|
+
smooth: true,
|
|
90
|
+
showSymbol: false,
|
|
91
|
+
data,
|
|
92
|
+
dataSum
|
|
93
|
+
};
|
|
94
|
+
});
|
|
95
|
+
result.sort((a, b) => b.dataSum - a.dataSum);
|
|
96
|
+
return result;
|
|
97
|
+
}, [baseData, metric, groupBys, validGroupByKeys]);
|
|
98
|
+
const series = useMemo(() => {
|
|
99
|
+
const list = seriesData.length > MAX_SECTORS ? seriesData.slice(0, MAX_SECTORS) : seriesData;
|
|
100
|
+
if (seriesData.length > MAX_SECTORS) {
|
|
101
|
+
message.warning(`数据量过大,仅绘制前 ${MAX_SECTORS} 条数据`);
|
|
102
|
+
}
|
|
103
|
+
return list.map(({ name, data, type, barMaxWidth, smooth, showSymbol }) => ({
|
|
104
|
+
name,
|
|
105
|
+
type,
|
|
106
|
+
barMaxWidth,
|
|
107
|
+
smooth,
|
|
108
|
+
showSymbol,
|
|
109
|
+
data
|
|
110
|
+
}));
|
|
111
|
+
}, [seriesData]);
|
|
112
|
+
const chartData = useMemo(() => {
|
|
113
|
+
return series.map((s) => __spreadValues({
|
|
114
|
+
name: s.name
|
|
115
|
+
}, metric.reduce((acc, m, i) => __spreadProps(__spreadValues({}, acc), { [m]: s.data[i] }), {})));
|
|
116
|
+
}, [series, metric]);
|
|
117
|
+
const yAxisFormatter = useMemo(() => {
|
|
118
|
+
var _a;
|
|
119
|
+
if (metric.length === 1) {
|
|
120
|
+
return (_a = columnConfigMap[metric[0]]) == null ? void 0 : _a.format;
|
|
121
|
+
}
|
|
122
|
+
return null;
|
|
123
|
+
}, [metric, columnConfigMap]);
|
|
124
|
+
const grid = {
|
|
125
|
+
top: 10,
|
|
126
|
+
left: 0,
|
|
127
|
+
right: 10,
|
|
128
|
+
bottom: 40,
|
|
129
|
+
containLabel: true
|
|
130
|
+
};
|
|
131
|
+
const legend = {
|
|
132
|
+
bottom: 0,
|
|
133
|
+
type: "scroll"
|
|
134
|
+
};
|
|
135
|
+
const xAxis = {
|
|
136
|
+
type: "category",
|
|
137
|
+
data: metric,
|
|
138
|
+
axisLine: {
|
|
139
|
+
lineStyle: {
|
|
140
|
+
color: "#EBEEF4"
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
axisLabel: {
|
|
144
|
+
color: "#9CA4B3",
|
|
145
|
+
fontSize: 12
|
|
146
|
+
},
|
|
147
|
+
axisTick: {
|
|
148
|
+
alignWithLabel: true
|
|
149
|
+
},
|
|
150
|
+
boundaryGap: true
|
|
151
|
+
};
|
|
152
|
+
const yAxis = {
|
|
153
|
+
type: "value",
|
|
154
|
+
splitNumber: 4,
|
|
155
|
+
// 设置Y轴坐标点数量
|
|
156
|
+
axisLine: {
|
|
157
|
+
show: true,
|
|
158
|
+
lineStyle: {
|
|
159
|
+
color: "#EBEEF4",
|
|
160
|
+
shadowOffsetY: -10,
|
|
161
|
+
shadowColor: "#EBEEF4"
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
axisLabel: {
|
|
165
|
+
color: "#999999",
|
|
166
|
+
fontSize: 12,
|
|
167
|
+
formatter: (value) => {
|
|
168
|
+
if (yAxisFormatter) {
|
|
169
|
+
if (yAxisFormatter === "currency") {
|
|
170
|
+
const [result2, unit2] = formatNumber(value, true);
|
|
171
|
+
return result2 + unit2;
|
|
172
|
+
}
|
|
173
|
+
if (yAxisFormatter === "percent") {
|
|
174
|
+
return new Decimal(value).mul(100) + "%";
|
|
175
|
+
}
|
|
176
|
+
return formatValue(value, yAxisFormatter);
|
|
177
|
+
}
|
|
178
|
+
const [result, unit] = formatNumber(value, true);
|
|
179
|
+
return result + unit;
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
splitLine: {
|
|
183
|
+
lineStyle: {
|
|
184
|
+
type: [2, 3],
|
|
185
|
+
// 虚线
|
|
186
|
+
color: "#E7E7E7"
|
|
187
|
+
// 背景线颜色
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
axisTick: {
|
|
191
|
+
show: true
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
const tooltipFormatter = (params) => {
|
|
195
|
+
var _a, _b;
|
|
196
|
+
const title = (_b = (_a = params[0]) == null ? void 0 : _a.axisValue) != null ? _b : "";
|
|
197
|
+
const filterParams = params.filter((f) => {
|
|
198
|
+
const { name, seriesName } = f;
|
|
199
|
+
if (name === "合计") {
|
|
200
|
+
return true;
|
|
201
|
+
} else if (chartData.some((dataItem) => {
|
|
202
|
+
return (dataItem == null ? void 0 : dataItem.name) === seriesName;
|
|
203
|
+
})) {
|
|
204
|
+
return true;
|
|
205
|
+
}
|
|
206
|
+
return false;
|
|
207
|
+
});
|
|
208
|
+
const tooltipDom = /* @__PURE__ */ React.createElement("div", { className: styles.tooltip }, /* @__PURE__ */ React.createElement("div", { className: styles.title }, title), /* @__PURE__ */ React.createElement("div", { className: styles.content }, filterParams.map((m) => {
|
|
209
|
+
var _a2;
|
|
210
|
+
const columnConfig = columnConfigMap[metric[0]];
|
|
211
|
+
const format = (_a2 = columnConfig == null ? void 0 : columnConfig.format) != null ? _a2 : "string";
|
|
212
|
+
const showValue = format === "currency" ? formatNumber(m.value, true) : formatValue(m.value, format);
|
|
213
|
+
const showValueText = showValue === "" || showValue[0] === "" ? "-" : showValue;
|
|
214
|
+
return /* @__PURE__ */ React.createElement("div", { className: styles.item, key: m.seriesName }, /* @__PURE__ */ React.createElement("div", { className: classNames(styles.point, styles.pointBar), style: { background: m.color } }), /* @__PURE__ */ React.createElement("div", { className: styles.category }, m.seriesName), /* @__PURE__ */ React.createElement("div", { className: styles.value }, showValueText));
|
|
215
|
+
})));
|
|
216
|
+
return ReactDOMServer.renderToStaticMarkup(tooltipDom);
|
|
217
|
+
};
|
|
218
|
+
const tooltip = {
|
|
219
|
+
trigger: "axis",
|
|
220
|
+
padding: 0,
|
|
221
|
+
confine: true,
|
|
222
|
+
enterable: true,
|
|
223
|
+
axisPointer: {
|
|
224
|
+
type: "shadow"
|
|
225
|
+
},
|
|
226
|
+
formatter: tooltipFormatter
|
|
227
|
+
};
|
|
228
|
+
const chartOptions = useMemo(() => {
|
|
229
|
+
return {
|
|
230
|
+
color: chartColors,
|
|
231
|
+
grid,
|
|
232
|
+
legend: __spreadProps(__spreadValues({}, legend), {
|
|
233
|
+
itemWidth: 10,
|
|
234
|
+
itemHeight: 10
|
|
235
|
+
}),
|
|
236
|
+
xAxis,
|
|
237
|
+
yAxis,
|
|
238
|
+
series,
|
|
239
|
+
tooltip
|
|
240
|
+
};
|
|
241
|
+
}, [series]);
|
|
242
|
+
useEffect(() => {
|
|
243
|
+
return () => {
|
|
244
|
+
if (chartInstanceRef.current) {
|
|
245
|
+
chartInstanceRef.current.dispose();
|
|
246
|
+
chartInstanceRef.current = null;
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
|
+
}, []);
|
|
250
|
+
useEffect(() => {
|
|
251
|
+
const container = chartContainerRef.current;
|
|
252
|
+
if (!container)
|
|
253
|
+
return;
|
|
254
|
+
let chart = chartInstanceRef.current;
|
|
255
|
+
if (!chart) {
|
|
256
|
+
chart = echarts.init(container);
|
|
257
|
+
chartInstanceRef.current = chart;
|
|
258
|
+
}
|
|
259
|
+
chart.setOption(chartOptions, true);
|
|
260
|
+
}, [chartOptions]);
|
|
261
|
+
useEffect(() => {
|
|
262
|
+
const chartElement = chartContainerRef.current;
|
|
263
|
+
if (!chartElement)
|
|
264
|
+
return;
|
|
265
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
266
|
+
var _a;
|
|
267
|
+
(_a = chartInstanceRef.current) == null ? void 0 : _a.resize();
|
|
268
|
+
});
|
|
269
|
+
resizeObserver.observe(chartElement);
|
|
270
|
+
return () => {
|
|
271
|
+
resizeObserver.unobserve(chartElement);
|
|
272
|
+
resizeObserver.disconnect();
|
|
273
|
+
};
|
|
274
|
+
}, []);
|
|
275
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, chartData.length > 0 ? /* @__PURE__ */ React.createElement(
|
|
276
|
+
"div",
|
|
277
|
+
{
|
|
278
|
+
ref: chartContainerRef,
|
|
279
|
+
className: styles.echarts,
|
|
280
|
+
style: { width: "100%", height: height || "100%", minHeight: 220 }
|
|
281
|
+
}
|
|
282
|
+
) : /* @__PURE__ */ React.createElement(Empty, { className: styles.empty, description: "暂无数据", image: Empty.PRESENTED_IMAGE_SIMPLE }));
|
|
283
|
+
};
|
|
284
|
+
var BarTotal_default = BarTotal;
|
|
285
|
+
export {
|
|
286
|
+
BarTotal_default as default
|
|
287
|
+
};
|
|
288
|
+
//# sourceMappingURL=BarTotal.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/business/YkCharts/BarTotal.tsx"],
|
|
4
|
+
"sourcesContent": ["/**\n * 基础分析-合计且有维度时的柱状图\n */\n\nimport { Empty, message } from 'antd';\nimport classNames from 'classnames';\nimport Decimal from 'decimal.js';\nimport * as echarts from 'echarts';\nimport React, { type FC, useEffect, useMemo, useRef } from 'react';\nimport ReactDOMServer from 'react-dom/server';\nimport { chartColors } from './constants';\nimport styles from './index.module.less';\nimport type { ColumnConfig, GroupByItem, TableData } from './typing';\nimport { formatNumber, formatValue } from './utils';\n\ntype RowItem = {\n [key: string]: number | string;\n};\n\ntype PageTypes = {\n count?: number;\n metric: string[];\n groupBys: GroupByItem[];\n tableData: TableData;\n baseData: RowItem[];\n columnConfigMap: { [key: string]: ColumnConfig };\n height?: number;\n};\n\nconst MAX_SECTORS = 500;\n\nconst BarTotal: FC<PageTypes> = ({\n count, // 指标显示数量\n metric, // 指标\n groupBys, // 维度\n tableData, // 表格数据\n baseData, // 基础数据\n columnConfigMap, // 列配置\n height,\n}) => {\n const chartContainerRef = useRef<HTMLDivElement | null>(null);\n const chartInstanceRef = useRef<echarts.ECharts | null>(null);\n\n const validGroupByKeys = useMemo(() => {\n return groupBys.filter((g) => Array.isArray(g.selected) && g.selected.length > 0).map((g) => g.key);\n }, [groupBys]);\n\n // 参照 Bar:从 baseData 提取实际存在的维度组合,不做笛卡尔积\n const seriesData = useMemo(() => {\n if (Array.isArray(groupBys) && groupBys.some((g) => Array.isArray(g.selected) && g.selected.length === 0)) {\n return [];\n }\n const validGroupBys = groupBys.filter((g) => Array.isArray(g.selected) && g.selected.length > 0);\n if (!baseData || baseData.length === 0) {\n return [];\n }\n const filteredBaseData = baseData.filter((item) => {\n return validGroupBys.every((g) => {\n const itemValue = String(item[g.key] ?? '');\n return g.selected.includes(itemValue);\n });\n });\n // 按维度组合聚合行(同一组合可能多行,如多日期需汇总指标)\n const byGroupBy = new Map<string, { name: string; rows: RowItem[] }>();\n filteredBaseData.forEach((item) => {\n const groupByValues = validGroupByKeys.map((key) => String(item[key] ?? '')).join('|');\n const name = validGroupByKeys.map((key) => item[key]).join(',');\n if (!byGroupBy.has(groupByValues)) {\n byGroupBy.set(groupByValues, { name, rows: [] });\n }\n byGroupBy.get(groupByValues)!.rows.push(item);\n });\n const result = Array.from(byGroupBy.entries()).map(([, { name, rows }]) => {\n const data = metric.map((m) => {\n const sum = rows.reduce((s, r) => s + (Number(r[m]) || 0), 0);\n return sum;\n });\n const dataSum = data.reduce((s, v) => s + (isNaN(v) ? 0 : v), 0);\n return {\n name,\n type: 'bar' as const,\n barMaxWidth: 20,\n smooth: true,\n showSymbol: false,\n data,\n dataSum,\n };\n });\n result.sort((a, b) => b.dataSum - a.dataSum);\n return result;\n }, [baseData, metric, groupBys, validGroupByKeys]);\n\n const series = useMemo(() => {\n const list = seriesData.length > MAX_SECTORS ? seriesData.slice(0, MAX_SECTORS) : seriesData;\n if (seriesData.length > MAX_SECTORS) {\n message.warning(`数据量过大,仅绘制前 ${MAX_SECTORS} 条数据`);\n }\n return list.map(({ name, data, type, barMaxWidth, smooth, showSymbol }) => ({\n name,\n type,\n barMaxWidth,\n smooth,\n showSymbol,\n data,\n }));\n }, [seriesData]);\n\n // 供 tooltip 使用:由 series 反推 chartData 结构\n const chartData = useMemo(() => {\n return series.map((s) => ({\n name: s.name,\n ...metric.reduce((acc, m, i) => ({ ...acc, [m]: s.data[i] }), {} as Record<string, number>),\n }));\n }, [series, metric]);\n\n // 获取y轴的格式化方式\n const yAxisFormatter = useMemo(() => {\n if (metric.length === 1) {\n return columnConfigMap[metric[0]]?.format;\n }\n return null;\n }, [metric, columnConfigMap]);\n\n const grid = {\n top: 10,\n left: 0,\n right: 10,\n bottom: 40,\n containLabel: true,\n };\n const legend = {\n bottom: 0,\n type: 'scroll',\n };\n const xAxis = {\n type: 'category',\n data: metric,\n axisLine: {\n lineStyle: {\n color: '#EBEEF4',\n },\n },\n axisLabel: {\n color: '#9CA4B3',\n fontSize: 12,\n },\n axisTick: {\n alignWithLabel: true,\n },\n boundaryGap: true,\n };\n const yAxis = {\n type: 'value',\n splitNumber: 4, // 设置Y轴坐标点数量\n axisLine: {\n show: true,\n lineStyle: {\n color: '#EBEEF4',\n shadowOffsetY: -10,\n shadowColor: '#EBEEF4',\n },\n },\n axisLabel: {\n color: '#999999',\n fontSize: 12,\n formatter: (value: number) => {\n // 目前只有一个指标时, Y轴进行格式化\n if (yAxisFormatter) {\n if (yAxisFormatter === 'currency') {\n const [result, unit] = formatNumber(value, true);\n return result + unit;\n }\n if (yAxisFormatter === 'percent') {\n return new Decimal(value).mul(100) + '%';\n }\n return formatValue(value, yAxisFormatter);\n }\n const [result, unit] = formatNumber(value, true);\n return result + unit;\n },\n },\n splitLine: {\n lineStyle: {\n type: [2, 3], // 虚线\n color: '#E7E7E7', // 背景线颜色\n },\n },\n axisTick: {\n show: true,\n },\n };\n const tooltipFormatter = (params: any) => {\n const title = params[0]?.axisValue ?? '';\n const filterParams = params.filter((f: any) => {\n const { name, seriesName } = f;\n if (name === '合计') {\n return true;\n } else if (\n chartData.some((dataItem) => {\n return dataItem?.name === seriesName;\n })\n ) {\n return true;\n }\n return false;\n });\n\n const tooltipDom = (\n <div className={styles.tooltip}>\n <div className={styles.title}>{title}</div>\n <div className={styles.content}>\n {filterParams.map((m: any) => {\n const columnConfig = columnConfigMap[metric[0]];\n const format = columnConfig?.format ?? 'string'; // 使用可选链和默认值\n const showValue = format === 'currency' ? formatNumber(m.value, true) : formatValue(m.value, format);\n const showValueText = showValue === '' || showValue[0] === '' ? '-' : showValue;\n return (\n <div className={styles.item} key={m.seriesName}>\n <div className={classNames(styles.point, styles.pointBar)} style={{ background: m.color }}></div>\n <div className={styles.category}>{m.seriesName}</div>\n <div className={styles.value}>{showValueText}</div>\n </div>\n );\n })}\n </div>\n </div>\n );\n return ReactDOMServer.renderToStaticMarkup(tooltipDom);\n };\n const tooltip = {\n trigger: 'axis',\n padding: 0,\n confine: true,\n enterable: true,\n axisPointer: {\n type: 'shadow',\n },\n formatter: tooltipFormatter,\n };\n\n // 图表配置\n const chartOptions = useMemo(() => {\n return {\n color: chartColors,\n grid,\n legend: {\n ...legend,\n itemWidth: 10,\n itemHeight: 10,\n },\n xAxis,\n yAxis,\n series,\n tooltip,\n };\n }, [series]);\n\n // 仅卸载时销毁实例\n useEffect(() => {\n return () => {\n if (chartInstanceRef.current) {\n chartInstanceRef.current.dispose();\n chartInstanceRef.current = null;\n }\n };\n }, []);\n\n // 配置变化时仅 setOption\n useEffect(() => {\n const container = chartContainerRef.current;\n if (!container) return;\n let chart = chartInstanceRef.current;\n if (!chart) {\n chart = echarts.init(container);\n chartInstanceRef.current = chart;\n }\n chart.setOption(chartOptions, true);\n }, [chartOptions]);\n\n // 监听容器大小变化(仅挂载时注册)\n useEffect(() => {\n const chartElement = chartContainerRef.current;\n if (!chartElement) return;\n const resizeObserver = new ResizeObserver(() => {\n chartInstanceRef.current?.resize();\n });\n resizeObserver.observe(chartElement);\n return () => {\n resizeObserver.unobserve(chartElement);\n resizeObserver.disconnect();\n };\n }, []);\n\n return (\n <>\n {chartData.length > 0 ? (\n <div\n ref={chartContainerRef}\n className={styles.echarts}\n style={{ width: '100%', height: height || '100%', minHeight: 220 }}\n ></div>\n ) : (\n <Empty className={styles.empty} description='暂无数据' image={Empty.PRESENTED_IMAGE_SIMPLE} />\n )}\n </>\n );\n};\n\nexport default BarTotal;\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["result", "unit", "_a"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { ColumnConfig, GroupByItem, SqlMetaConfig, TableData } from './typing';
|
|
3
|
+
type RowItem = {
|
|
4
|
+
[key: string]: number | string;
|
|
5
|
+
};
|
|
6
|
+
type PageTypes = {
|
|
7
|
+
count?: number;
|
|
8
|
+
metric: string[];
|
|
9
|
+
groupBys: GroupByItem[];
|
|
10
|
+
tableData: TableData;
|
|
11
|
+
baseData: RowItem[];
|
|
12
|
+
columnConfigMap: {
|
|
13
|
+
[key: string]: ColumnConfig;
|
|
14
|
+
};
|
|
15
|
+
sqlFormatMap?: {
|
|
16
|
+
[key: string]: SqlMetaConfig;
|
|
17
|
+
};
|
|
18
|
+
height?: number;
|
|
19
|
+
};
|
|
20
|
+
declare const _default: React.NamedExoticComponent<PageTypes>;
|
|
21
|
+
export default _default;
|
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defProps = Object.defineProperties;
|
|
3
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
7
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8
|
+
var __spreadValues = (a, b) => {
|
|
9
|
+
for (var prop in b || (b = {}))
|
|
10
|
+
if (__hasOwnProp.call(b, prop))
|
|
11
|
+
__defNormalProp(a, prop, b[prop]);
|
|
12
|
+
if (__getOwnPropSymbols)
|
|
13
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
14
|
+
if (__propIsEnum.call(b, prop))
|
|
15
|
+
__defNormalProp(a, prop, b[prop]);
|
|
16
|
+
}
|
|
17
|
+
return a;
|
|
18
|
+
};
|
|
19
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
|
+
|
|
21
|
+
// src/business/YkCharts/Line.tsx
|
|
22
|
+
import { Empty, message } from "antd";
|
|
23
|
+
import Decimal from "decimal.js";
|
|
24
|
+
import * as echarts from "echarts";
|
|
25
|
+
import { isEmpty } from "lodash";
|
|
26
|
+
import React, { memo, useEffect, useMemo, useRef } from "react";
|
|
27
|
+
import ReactDOMServer from "react-dom/server";
|
|
28
|
+
import { chartColors } from "./constants";
|
|
29
|
+
import styles from "./index.module.less";
|
|
30
|
+
import { formatNumber, formatValue, sqlFormat } from "./utils";
|
|
31
|
+
var MAX_SECTORS = 500;
|
|
32
|
+
var Line = ({
|
|
33
|
+
count,
|
|
34
|
+
// 指标显示数量
|
|
35
|
+
metric,
|
|
36
|
+
// 指标
|
|
37
|
+
groupBys,
|
|
38
|
+
// 维度
|
|
39
|
+
tableData,
|
|
40
|
+
// 表格数据
|
|
41
|
+
baseData,
|
|
42
|
+
// 基础数据
|
|
43
|
+
columnConfigMap,
|
|
44
|
+
// 列配置
|
|
45
|
+
sqlFormatMap,
|
|
46
|
+
// 列配置(用于SQL可视化中的格式化处理,SQL中的格式化走了另一套逻辑)
|
|
47
|
+
height
|
|
48
|
+
}) => {
|
|
49
|
+
const { x = [], x_field, group_by } = tableData;
|
|
50
|
+
const chartContainerRef = useRef(null);
|
|
51
|
+
const chartInstanceRef = useRef(null);
|
|
52
|
+
const onlyOneMetric = useMemo(() => {
|
|
53
|
+
return metric.length === 1;
|
|
54
|
+
}, [metric]);
|
|
55
|
+
const seriesData = useMemo(() => {
|
|
56
|
+
if (Array.isArray(groupBys) && groupBys.some((g) => Array.isArray(g.selected) && g.selected.length === 0)) {
|
|
57
|
+
return [];
|
|
58
|
+
}
|
|
59
|
+
const validGroupBys = groupBys.filter((g) => Array.isArray(g.selected) && g.selected.length > 0);
|
|
60
|
+
const validGroupByKeys = validGroupBys.map((g) => g.key);
|
|
61
|
+
if (!baseData || baseData.length === 0) {
|
|
62
|
+
return [];
|
|
63
|
+
}
|
|
64
|
+
const filteredBaseData = baseData.filter((item) => {
|
|
65
|
+
return validGroupBys.every((g) => {
|
|
66
|
+
var _a;
|
|
67
|
+
const itemValue = String((_a = item[g.key]) != null ? _a : "");
|
|
68
|
+
return g.selected.includes(itemValue);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
const dataIndexMap = /* @__PURE__ */ new Map();
|
|
72
|
+
const existingCombinations = /* @__PURE__ */ new Map();
|
|
73
|
+
const getName = (category, groupByObj) => {
|
|
74
|
+
if (group_by && group_by.length > 0) {
|
|
75
|
+
if (onlyOneMetric) {
|
|
76
|
+
return group_by.map((g) => groupByObj[g]).join(",");
|
|
77
|
+
}
|
|
78
|
+
return [category, ...group_by.map((g) => groupByObj[g])].join(",");
|
|
79
|
+
}
|
|
80
|
+
return category;
|
|
81
|
+
};
|
|
82
|
+
filteredBaseData.forEach((item) => {
|
|
83
|
+
const groupByValues = validGroupByKeys.map((key) => {
|
|
84
|
+
var _a;
|
|
85
|
+
return String((_a = item[key]) != null ? _a : "");
|
|
86
|
+
}).join("|");
|
|
87
|
+
metric.forEach((cat) => {
|
|
88
|
+
const key = `${item[x_field]}|${groupByValues}|${cat}`;
|
|
89
|
+
dataIndexMap.set(key, item);
|
|
90
|
+
const combinationKey = `${groupByValues}|${cat}`;
|
|
91
|
+
if (!existingCombinations.has(combinationKey)) {
|
|
92
|
+
const groupByObj = { category: cat };
|
|
93
|
+
validGroupByKeys.forEach((gKey) => {
|
|
94
|
+
groupByObj[gKey] = item[gKey];
|
|
95
|
+
});
|
|
96
|
+
const name = getName(cat, groupByObj);
|
|
97
|
+
existingCombinations.set(combinationKey, {
|
|
98
|
+
groupByValues,
|
|
99
|
+
category: cat,
|
|
100
|
+
groupByObj,
|
|
101
|
+
name
|
|
102
|
+
// 预先计算好的 name
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
const result = Array.from(existingCombinations.values()).map(({ groupByValues, category, name }) => {
|
|
108
|
+
const data = new Array(x.length);
|
|
109
|
+
for (let i = 0; i < x.length; i++) {
|
|
110
|
+
const item = x[i];
|
|
111
|
+
const key = `${item}|${groupByValues}|${category}`;
|
|
112
|
+
const itemData = dataIndexMap.get(key);
|
|
113
|
+
data[i] = itemData == null ? void 0 : itemData[category];
|
|
114
|
+
}
|
|
115
|
+
return {
|
|
116
|
+
name,
|
|
117
|
+
type: "line",
|
|
118
|
+
smooth: true,
|
|
119
|
+
showSymbol: true,
|
|
120
|
+
symbol: "emptyCircle",
|
|
121
|
+
symbolSize: 0.8,
|
|
122
|
+
lineStyle: {
|
|
123
|
+
width: 1.5
|
|
124
|
+
},
|
|
125
|
+
emphasis: {
|
|
126
|
+
scale: 8
|
|
127
|
+
},
|
|
128
|
+
data,
|
|
129
|
+
dataSum: data.reduce((sum, val) => {
|
|
130
|
+
const num = typeof val === "number" ? val : 0;
|
|
131
|
+
return sum + (isNaN(num) ? 0 : num);
|
|
132
|
+
}, 0)
|
|
133
|
+
};
|
|
134
|
+
});
|
|
135
|
+
const sortedResult = result.sort((a, b) => {
|
|
136
|
+
const sumA = a.dataSum;
|
|
137
|
+
const sumB = b.dataSum;
|
|
138
|
+
return sumB - sumA;
|
|
139
|
+
});
|
|
140
|
+
return sortedResult;
|
|
141
|
+
}, [baseData, metric, groupBys, x, x_field, group_by, onlyOneMetric]);
|
|
142
|
+
const yAxisFormatter = useMemo(() => {
|
|
143
|
+
var _a, _b;
|
|
144
|
+
if (!isEmpty(sqlFormatMap) && metric.length > 0) {
|
|
145
|
+
const format = (_a = sqlFormatMap[metric[0]]) == null ? void 0 : _a.format;
|
|
146
|
+
if ((format == null ? void 0 : format.type) === "currency") {
|
|
147
|
+
return "number";
|
|
148
|
+
}
|
|
149
|
+
if ((format == null ? void 0 : format.type) === "percent") {
|
|
150
|
+
return "percent";
|
|
151
|
+
}
|
|
152
|
+
if ((format == null ? void 0 : format.decimals) > 0) {
|
|
153
|
+
return "decimal";
|
|
154
|
+
}
|
|
155
|
+
return "number";
|
|
156
|
+
}
|
|
157
|
+
if (metric.length === 1) {
|
|
158
|
+
return (_b = columnConfigMap[metric[0]]) == null ? void 0 : _b.format;
|
|
159
|
+
}
|
|
160
|
+
return null;
|
|
161
|
+
}, [metric, columnConfigMap, sqlFormatMap]);
|
|
162
|
+
const grid = {
|
|
163
|
+
top: 10,
|
|
164
|
+
left: 5,
|
|
165
|
+
right: 10,
|
|
166
|
+
bottom: 40,
|
|
167
|
+
containLabel: true
|
|
168
|
+
};
|
|
169
|
+
const legend = {
|
|
170
|
+
bottom: 0,
|
|
171
|
+
type: "scroll",
|
|
172
|
+
itemWidth: 13,
|
|
173
|
+
itemStyle: {
|
|
174
|
+
opacity: 0
|
|
175
|
+
},
|
|
176
|
+
lineStyle: {
|
|
177
|
+
width: 2,
|
|
178
|
+
type: "solid"
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
const xAxis = {
|
|
182
|
+
type: "category",
|
|
183
|
+
data: x,
|
|
184
|
+
axisLine: {
|
|
185
|
+
lineStyle: {
|
|
186
|
+
color: "#EBEEF4"
|
|
187
|
+
}
|
|
188
|
+
},
|
|
189
|
+
axisLabel: {
|
|
190
|
+
color: "#9CA4B3",
|
|
191
|
+
fontSize: 12
|
|
192
|
+
},
|
|
193
|
+
axisTick: {
|
|
194
|
+
alignWithLabel: true
|
|
195
|
+
},
|
|
196
|
+
boundaryGap: true
|
|
197
|
+
};
|
|
198
|
+
const yAxis = {
|
|
199
|
+
type: "value",
|
|
200
|
+
splitNumber: 4,
|
|
201
|
+
// 设置Y轴坐标点数量
|
|
202
|
+
axisLine: {
|
|
203
|
+
show: true,
|
|
204
|
+
lineStyle: {
|
|
205
|
+
color: "#EBEEF4",
|
|
206
|
+
shadowOffsetY: -10,
|
|
207
|
+
shadowColor: "#EBEEF4"
|
|
208
|
+
}
|
|
209
|
+
},
|
|
210
|
+
axisLabel: {
|
|
211
|
+
color: "#999999",
|
|
212
|
+
fontSize: 12,
|
|
213
|
+
padding: [0, 0, 0, 5],
|
|
214
|
+
formatter: (value) => {
|
|
215
|
+
if (yAxisFormatter === "percent") {
|
|
216
|
+
return new Decimal(value).mul(100) + "%";
|
|
217
|
+
}
|
|
218
|
+
if (yAxisFormatter === "decimal") {
|
|
219
|
+
return formatValue(value, yAxisFormatter);
|
|
220
|
+
}
|
|
221
|
+
const [result, unit] = formatNumber(value, true);
|
|
222
|
+
return result + unit;
|
|
223
|
+
}
|
|
224
|
+
},
|
|
225
|
+
splitLine: {
|
|
226
|
+
lineStyle: {
|
|
227
|
+
type: [2, 3],
|
|
228
|
+
// 虚线
|
|
229
|
+
color: "#E7E7E7"
|
|
230
|
+
// 背景线颜色
|
|
231
|
+
}
|
|
232
|
+
},
|
|
233
|
+
axisTick: {
|
|
234
|
+
show: true
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
const tooltipFormatter = (params) => {
|
|
238
|
+
var _a, _b;
|
|
239
|
+
const title = (_b = (_a = params[0]) == null ? void 0 : _a.axisValue) != null ? _b : "";
|
|
240
|
+
const tooltipDom = /* @__PURE__ */ React.createElement("div", { className: styles.tooltip }, /* @__PURE__ */ React.createElement("div", { className: styles.title }, /* @__PURE__ */ React.createElement("span", null, title), /* @__PURE__ */ React.createElement("span", { style: { float: "right", paddingRight: 10 } }, onlyOneMetric && metric.length === 1 ? " " + metric[0] : "")), /* @__PURE__ */ React.createElement("div", { className: styles.content }, params.map((m) => {
|
|
241
|
+
var _a2, _b2;
|
|
242
|
+
const metricName = onlyOneMetric && metric.length === 1 ? metric[0] : m.seriesName.split(",")[0];
|
|
243
|
+
const columnConfig = columnConfigMap[metricName];
|
|
244
|
+
const format = (_a2 = columnConfig == null ? void 0 : columnConfig.format) != null ? _a2 : "string";
|
|
245
|
+
let showValue = format === "currency" ? formatNumber(m.value, true) : formatValue(m.value, format);
|
|
246
|
+
if (!isEmpty(sqlFormatMap) && metric.length > 0) {
|
|
247
|
+
const format2 = (_b2 = sqlFormatMap[metricName]) == null ? void 0 : _b2.format;
|
|
248
|
+
showValue = sqlFormat(m.value, format2);
|
|
249
|
+
}
|
|
250
|
+
const showValueText = showValue === "" || showValue[0] === "" ? "-" : showValue;
|
|
251
|
+
return /* @__PURE__ */ React.createElement("div", { className: styles.item, key: m.seriesName }, /* @__PURE__ */ React.createElement("div", { className: styles.point, style: { background: m.color } }), /* @__PURE__ */ React.createElement("div", { className: styles.category }, m.seriesName), /* @__PURE__ */ React.createElement("div", { className: styles.value }, showValueText));
|
|
252
|
+
})));
|
|
253
|
+
return ReactDOMServer.renderToStaticMarkup(tooltipDom);
|
|
254
|
+
};
|
|
255
|
+
const tooltip = {
|
|
256
|
+
trigger: "axis",
|
|
257
|
+
padding: 0,
|
|
258
|
+
confine: true,
|
|
259
|
+
enterable: true,
|
|
260
|
+
axisPointer: {
|
|
261
|
+
type: "line",
|
|
262
|
+
// 设置悬浮指针为线
|
|
263
|
+
lineStyle: {
|
|
264
|
+
color: "#EBEEF4",
|
|
265
|
+
// 设置线的颜色
|
|
266
|
+
type: "dashed"
|
|
267
|
+
// 设置虚线样式
|
|
268
|
+
}
|
|
269
|
+
},
|
|
270
|
+
formatter: tooltipFormatter
|
|
271
|
+
};
|
|
272
|
+
const chartOptions = useMemo(() => {
|
|
273
|
+
if (seriesData.length > MAX_SECTORS) {
|
|
274
|
+
message.warning(`数据量过大,仅绘制前 ${MAX_SECTORS} 条数据`);
|
|
275
|
+
}
|
|
276
|
+
const result = {
|
|
277
|
+
color: chartColors,
|
|
278
|
+
grid,
|
|
279
|
+
legend: __spreadProps(__spreadValues({}, legend), {
|
|
280
|
+
itemWidth: 13,
|
|
281
|
+
itemStyle: {
|
|
282
|
+
opacity: 0
|
|
283
|
+
},
|
|
284
|
+
lineStyle: {
|
|
285
|
+
width: 2,
|
|
286
|
+
type: "solid"
|
|
287
|
+
}
|
|
288
|
+
}),
|
|
289
|
+
xAxis,
|
|
290
|
+
yAxis,
|
|
291
|
+
// 前端这里做个限制,防止数据量过大导致性能问题
|
|
292
|
+
series: seriesData.length > MAX_SECTORS ? seriesData.slice(0, MAX_SECTORS) : seriesData,
|
|
293
|
+
tooltip
|
|
294
|
+
};
|
|
295
|
+
return result;
|
|
296
|
+
}, [seriesData]);
|
|
297
|
+
useEffect(() => {
|
|
298
|
+
if (!chartContainerRef.current)
|
|
299
|
+
return;
|
|
300
|
+
let chart = chartInstanceRef.current;
|
|
301
|
+
if (!chart) {
|
|
302
|
+
chart = echarts.init(chartContainerRef.current);
|
|
303
|
+
chartInstanceRef.current = chart;
|
|
304
|
+
}
|
|
305
|
+
chart == null ? void 0 : chart.setOption(chartOptions, true);
|
|
306
|
+
return () => {
|
|
307
|
+
if (chartInstanceRef.current) {
|
|
308
|
+
chartInstanceRef.current.dispose();
|
|
309
|
+
chartInstanceRef.current = null;
|
|
310
|
+
}
|
|
311
|
+
};
|
|
312
|
+
}, [chartOptions]);
|
|
313
|
+
useEffect(() => {
|
|
314
|
+
const chartElement = chartContainerRef.current;
|
|
315
|
+
if (!chartElement)
|
|
316
|
+
return;
|
|
317
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
318
|
+
const chart = chartInstanceRef.current;
|
|
319
|
+
if (chart) {
|
|
320
|
+
chart.resize();
|
|
321
|
+
}
|
|
322
|
+
});
|
|
323
|
+
resizeObserver.observe(chartElement);
|
|
324
|
+
return () => {
|
|
325
|
+
resizeObserver.unobserve(chartElement);
|
|
326
|
+
resizeObserver.disconnect();
|
|
327
|
+
};
|
|
328
|
+
}, [seriesData]);
|
|
329
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, seriesData.length > 0 ? /* @__PURE__ */ React.createElement(
|
|
330
|
+
"div",
|
|
331
|
+
{
|
|
332
|
+
ref: chartContainerRef,
|
|
333
|
+
className: styles.echarts,
|
|
334
|
+
style: { width: "100%", height: height || "100%", minHeight: 220 }
|
|
335
|
+
}
|
|
336
|
+
) : /* @__PURE__ */ React.createElement(Empty, { className: styles.empty, description: "暂无数据", image: Empty.PRESENTED_IMAGE_SIMPLE }));
|
|
337
|
+
};
|
|
338
|
+
var Line_default = memo(Line);
|
|
339
|
+
export {
|
|
340
|
+
Line_default as default
|
|
341
|
+
};
|
|
342
|
+
//# sourceMappingURL=Line.js.map
|