@agions/taroviz 1.11.1 → 2.0.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.
- package/CHANGELOG.md +245 -0
- package/README.md +104 -302
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/vendors.js +1 -0
- package/dist/cjs/vendors~echarts.js +1 -0
- package/dist/esm/index.js +1 -58151
- package/dist/esm/vendors.js +1 -0
- package/dist/esm/vendors~echarts.js +1 -0
- package/package.json +19 -25
- package/src/adapters/MiniAppAdapter.ts +136 -0
- package/src/adapters/__tests__/index.test.ts +1 -1
- package/src/adapters/h5/__tests__/index.test.ts +4 -2
- package/src/adapters/h5/index.ts +63 -64
- package/src/adapters/harmony/index.ts +23 -245
- package/src/adapters/index.ts +49 -45
- package/src/adapters/swan/index.ts +6 -69
- package/src/adapters/tt/index.ts +7 -70
- package/src/adapters/types.ts +25 -58
- package/src/adapters/weapp/index.ts +6 -69
- package/src/charts/__tests__/testUtils.tsx +87 -0
- package/src/charts/boxplot/__tests__/index.test.tsx +49 -103
- package/src/charts/boxplot/index.tsx +2 -1
- package/src/charts/boxplot/types.ts +17 -16
- package/src/charts/common/BaseChartWrapper.tsx +90 -82
- package/src/charts/common/__mocks__/BaseChartWrapper.tsx +17 -0
- package/src/charts/createChartComponent.tsx +36 -0
- package/src/charts/createOptionChartComponent.tsx +32 -0
- package/src/charts/funnel/__tests__/index.test.tsx +99 -0
- package/src/charts/funnel/index.tsx +60 -10
- package/src/charts/funnel/types.ts +6 -0
- package/src/charts/graph/__tests__/index.test.tsx +102 -33
- package/src/charts/graph/index.tsx +66 -9
- package/src/charts/graph/types.ts +6 -0
- package/src/charts/heatmap/__tests__/index.test.tsx +139 -0
- package/src/charts/heatmap/index.tsx +103 -10
- package/src/charts/heatmap/types.ts +6 -0
- package/src/charts/index.ts +74 -26
- package/src/charts/liquid/__tests__/index.test.tsx +52 -0
- package/src/charts/liquid/index.tsx +239 -182
- package/src/charts/liquid/types.ts +11 -11
- package/src/charts/parallel/__tests__/index.test.tsx +40 -67
- package/src/charts/parallel/index.tsx +2 -1
- package/src/charts/parallel/types.ts +19 -18
- package/src/charts/radar/__tests__/index.test.tsx +210 -0
- package/src/charts/radar/index.tsx +143 -10
- package/src/charts/radar/types.ts +13 -0
- package/src/charts/sankey/__tests__/index.test.tsx +124 -0
- package/src/charts/sankey/index.tsx +62 -10
- package/src/charts/sankey/types.ts +6 -0
- package/src/charts/tree/__tests__/index.test.tsx +71 -0
- package/src/charts/tree/index.tsx +5 -2
- package/src/charts/tree/types.ts +9 -9
- package/src/charts/types.ts +208 -106
- package/src/charts/utils.ts +9 -7
- package/src/charts/wordcloud/__tests__/index.test.tsx +98 -31
- package/src/charts/wordcloud/index.tsx +75 -9
- package/src/charts/wordcloud/types.ts +6 -0
- package/src/components/DataFilter/index.tsx +32 -10
- package/src/core/animation/types.ts +6 -6
- package/src/core/components/Annotation.tsx +6 -7
- package/src/core/components/BaseChart.tsx +110 -168
- package/src/core/components/ErrorBoundary.tsx +17 -4
- package/src/core/components/LazyChart.tsx +54 -55
- package/src/core/components/hooks/index.ts +6 -2
- package/src/core/components/hooks/useChartInit.ts +6 -3
- package/src/core/components/hooks/usePerformance.ts +8 -2
- package/src/core/components/hooks/useVirtualScroll.ts +2 -1
- package/src/core/index.ts +1 -1
- package/src/core/themes/ThemeManager.ts +1 -1
- package/src/core/types/common.ts +2 -1
- package/src/core/types/index.ts +0 -12
- package/src/core/types/platform.ts +3 -5
- package/src/core/utils/__tests__/deepClone.test.ts +317 -0
- package/src/core/utils/__tests__/index.test.ts +2 -1
- package/src/core/utils/chartInstances.ts +13 -0
- package/src/core/utils/common.ts +20 -29
- package/src/core/utils/deepClone.ts +114 -0
- package/src/core/utils/download.ts +128 -0
- package/src/core/utils/drillDown.ts +34 -353
- package/src/core/utils/drillDownHelpers.ts +426 -0
- package/src/core/utils/events.ts +12 -0
- package/src/core/utils/export/ExportUtils.ts +36 -67
- package/src/core/utils/format.ts +44 -0
- package/src/core/utils/index.ts +21 -154
- package/src/core/utils/merge.ts +25 -0
- package/src/core/utils/performance/PerformanceAnalyzer.ts +38 -21
- package/src/core/utils/performance/hooks.ts +7 -0
- package/src/core/utils/performance/index.ts +2 -0
- package/src/{hooks → core/utils/performance}/useAnimation.ts +45 -41
- package/src/core/utils/performance/useDataZoom.ts +324 -0
- package/src/{hooks → core/utils/performance}/usePerformance.ts +49 -41
- package/src/core/utils/performance/usePerformanceHooks.ts +278 -0
- package/src/core/utils/performanceUtils.ts +310 -0
- package/src/core/utils/runtime.ts +190 -0
- package/src/core/utils/setOptionUtils.ts +59 -0
- package/src/core/version.ts +14 -0
- package/src/editor/EnhancedThemeEditor.tsx +362 -540
- package/src/editor/ThemeEditor.tsx +55 -321
- package/src/editor/components/ThemeBasicSettings.tsx +113 -0
- package/src/editor/components/ThemeColorEditor.tsx +105 -0
- package/src/editor/components/ThemeSelector.tsx +70 -0
- package/src/editor/hooks/useThemeEditorState.ts +201 -0
- package/src/editor/index.ts +10 -2
- package/src/hooks/__tests__/index.test.tsx +3 -1
- package/src/hooks/chartConnectHelpers.ts +341 -0
- package/src/hooks/index.ts +55 -660
- package/src/hooks/types.ts +189 -0
- package/src/hooks/useChartAutoResize.ts +73 -0
- package/src/hooks/useChartConnect.ts +92 -238
- package/src/hooks/useChartDownload.ts +25 -27
- package/src/hooks/useChartHistory.ts +34 -49
- package/src/hooks/useChartInit.ts +59 -0
- package/src/hooks/useChartOptions.ts +259 -0
- package/src/hooks/useChartPerformance.ts +109 -0
- package/src/hooks/useChartSelection.ts +52 -49
- package/src/hooks/useChartTheme.ts +51 -0
- package/src/hooks/useDataTransform.ts +19 -4
- package/src/hooks/utils/chartDownloadUtils.ts +40 -53
- package/src/hooks/utils/dataTransformUtils.ts +22 -0
- package/src/index.ts +48 -34
- package/src/main.tsx +4 -9
- package/src/react-dom.d.ts +3 -3
- package/src/themes/index.ts +30 -855
- package/src/themes/palettes/blue-green.ts +13 -0
- package/src/themes/palettes/chalk.ts +13 -0
- package/src/themes/palettes/cyber.ts +44 -0
- package/src/themes/palettes/dark.ts +52 -0
- package/src/themes/palettes/default.ts +52 -0
- package/src/themes/palettes/elegant.ts +34 -0
- package/src/themes/palettes/forest.ts +13 -0
- package/src/themes/palettes/glass.ts +49 -0
- package/src/themes/palettes/golden.ts +13 -0
- package/src/themes/palettes/neon.ts +43 -0
- package/src/themes/palettes/ocean.ts +39 -0
- package/src/themes/palettes/pastel.ts +37 -0
- package/src/themes/palettes/purple-passion.ts +13 -0
- package/src/themes/palettes/retro.ts +33 -0
- package/src/themes/palettes/sunset.ts +40 -0
- package/src/themes/palettes/walden.ts +13 -0
- package/src/themes/registry.ts +184 -0
- package/src/themes/types.ts +213 -0
- package/src/charts/bar/__tests__/index.test.tsx +0 -113
- package/src/charts/bar/index.tsx +0 -14
- package/src/charts/candlestick/__tests__/index.test.tsx +0 -40
- package/src/charts/candlestick/index.tsx +0 -13
- package/src/charts/gauge/index.tsx +0 -14
- package/src/charts/line/__tests__/index.test.tsx +0 -107
- package/src/charts/line/index.tsx +0 -15
- package/src/charts/pie/__tests__/index.test.tsx +0 -112
- package/src/charts/pie/index.tsx +0 -14
- package/src/charts/scatter/index.tsx +0 -14
- package/src/charts/sunburst/index.tsx +0 -18
- package/src/charts/treemap/index.tsx +0 -18
- package/src/core/utils/codeGenerator/CodeGenerator.ts +0 -669
- package/src/core/utils/codeGenerator/index.ts +0 -13
- package/src/core/utils/codeGenerator/types.ts +0 -198
- package/src/core/utils/configGenerator/ConfigGenerator.ts +0 -583
- package/src/core/utils/configGenerator/index.ts +0 -13
- package/src/core/utils/configGenerator/types.ts +0 -445
- package/src/core/utils/debug/DebugPanel.tsx +0 -637
- package/src/core/utils/debug/debugger.ts +0 -322
- package/src/core/utils/debug/index.ts +0 -21
- package/src/core/utils/debug/types.ts +0 -142
- package/src/hooks/useDataZoom.ts +0 -323
package/src/core/utils/common.ts
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Environment detection utilities
|
|
3
|
+
*
|
|
4
|
+
* Backward-compatible re-exports that delegate to the unified detectRuntime()
|
|
5
|
+
* in ./runtime.ts. New code should import detectRuntime() directly.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { detectRuntime as _detectRuntime } from './runtime';
|
|
9
|
+
|
|
10
|
+
export { detectRuntime, resetRuntimeCache } from './runtime';
|
|
11
|
+
export type { RuntimeInfo, MiniAppType } from './runtime';
|
|
12
|
+
|
|
1
13
|
/**
|
|
2
14
|
* 获取DOM元素
|
|
3
15
|
* @param selector 选择器或DOM元素
|
|
@@ -21,14 +33,12 @@ export const isBrowser = typeof window !== 'undefined' && typeof document !== 'u
|
|
|
21
33
|
* @returns 是否为NodeJS环境
|
|
22
34
|
*/
|
|
23
35
|
export const isNode = (() => {
|
|
24
|
-
// 更可靠的环境检测:检查是否是真正的 Node.js 环境
|
|
25
|
-
// 而不是打包后的代码(如 webpack 定义的 process.env)
|
|
26
36
|
try {
|
|
27
37
|
return (
|
|
28
38
|
typeof process !== 'undefined' &&
|
|
29
|
-
process.versions &&
|
|
30
|
-
process.versions.node &&
|
|
31
|
-
Object.prototype.toString.call(globalThis.process) === '[object process]'
|
|
39
|
+
(process as any).versions &&
|
|
40
|
+
(process as any).versions.node &&
|
|
41
|
+
Object.prototype.toString.call((globalThis as any).process) === '[object process]'
|
|
32
42
|
);
|
|
33
43
|
} catch {
|
|
34
44
|
return false;
|
|
@@ -40,32 +50,13 @@ export const isNode = (() => {
|
|
|
40
50
|
* @returns 是否为React Native环境
|
|
41
51
|
*/
|
|
42
52
|
export const isReactNative =
|
|
43
|
-
typeof navigator !== 'undefined' && navigator.product === 'ReactNative';
|
|
53
|
+
typeof navigator !== 'undefined' && (navigator as any).product === 'ReactNative';
|
|
44
54
|
|
|
45
55
|
/**
|
|
46
56
|
* 是否为小程序环境
|
|
57
|
+
*
|
|
58
|
+
* Delegates to detectRuntime() for unified detection.
|
|
59
|
+
* Cached internally — repeated calls are cheap.
|
|
47
60
|
* @returns 是否为小程序环境
|
|
48
61
|
*/
|
|
49
|
-
export const isMiniApp = (): boolean =>
|
|
50
|
-
// 使用类型断言来安全地检查全局变量
|
|
51
|
-
const globalObj =
|
|
52
|
-
typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : {};
|
|
53
|
-
|
|
54
|
-
if (typeof (globalObj as any).wx !== 'undefined') {
|
|
55
|
-
return true;
|
|
56
|
-
}
|
|
57
|
-
if (typeof (globalObj as any).my !== 'undefined') {
|
|
58
|
-
return true;
|
|
59
|
-
}
|
|
60
|
-
if (typeof (globalObj as any).swan !== 'undefined') {
|
|
61
|
-
return true;
|
|
62
|
-
}
|
|
63
|
-
if (typeof (globalObj as any).tt !== 'undefined') {
|
|
64
|
-
return true;
|
|
65
|
-
}
|
|
66
|
-
if (typeof (globalObj as any).jd !== 'undefined') {
|
|
67
|
-
return true;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
return false;
|
|
71
|
-
};
|
|
62
|
+
export const isMiniApp = (): boolean => _detectRuntime().isMiniApp;
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hand-written deep clone utility for ECharts option objects.
|
|
3
|
+
* Handles all JS types, circular references, and preserves function references.
|
|
4
|
+
*/
|
|
5
|
+
export function deepClone<T>(value: T, seen?: WeakMap<object, unknown>): T {
|
|
6
|
+
// primitives, null, undefined
|
|
7
|
+
if (value === null || value === undefined) return value;
|
|
8
|
+
if (typeof value !== 'object' && typeof value !== 'function') return value;
|
|
9
|
+
// preserve function references
|
|
10
|
+
if (typeof value === 'function') return value;
|
|
11
|
+
|
|
12
|
+
// circular reference handling
|
|
13
|
+
if (!seen) seen = new WeakMap();
|
|
14
|
+
if (seen.has(value as object)) return seen.get(value as object) as T;
|
|
15
|
+
|
|
16
|
+
// Date
|
|
17
|
+
if (value instanceof Date) {
|
|
18
|
+
const d = new Date(value.getTime());
|
|
19
|
+
seen.set(value as object, d);
|
|
20
|
+
return d as unknown as T;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// RegExp
|
|
24
|
+
if (value instanceof RegExp) {
|
|
25
|
+
const r = new RegExp(value.source, value.flags);
|
|
26
|
+
seen.set(value as object, r);
|
|
27
|
+
return r as unknown as T;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Map
|
|
31
|
+
if (value instanceof Map) {
|
|
32
|
+
const m = new Map();
|
|
33
|
+
seen.set(value as object, m);
|
|
34
|
+
value.forEach((v, k) => {
|
|
35
|
+
m.set(deepClone(k, seen), deepClone(v, seen));
|
|
36
|
+
});
|
|
37
|
+
return m as unknown as T;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Set
|
|
41
|
+
if (value instanceof Set) {
|
|
42
|
+
const s = new Set();
|
|
43
|
+
seen.set(value as object, s);
|
|
44
|
+
value.forEach((v) => {
|
|
45
|
+
s.add(deepClone(v, seen));
|
|
46
|
+
});
|
|
47
|
+
return s as unknown as T;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Array
|
|
51
|
+
if (Array.isArray(value)) {
|
|
52
|
+
const arr: unknown[] = [];
|
|
53
|
+
seen.set(value as object, arr);
|
|
54
|
+
for (let i = 0; i < value.length; i++) {
|
|
55
|
+
arr[i] = deepClone(value[i], seen);
|
|
56
|
+
}
|
|
57
|
+
return arr as unknown as T;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Plain object
|
|
61
|
+
const clone = {} as Record<string, unknown>;
|
|
62
|
+
seen.set(value as object, clone);
|
|
63
|
+
for (const key of Object.keys(value as object)) {
|
|
64
|
+
clone[key] = deepClone((value as Record<string, unknown>)[key], seen);
|
|
65
|
+
}
|
|
66
|
+
return clone as T;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Deep merge source into target. Returns a new object.
|
|
71
|
+
* Arrays are replaced, not merged. Objects are merged recursively.
|
|
72
|
+
*/
|
|
73
|
+
export function deepMerge<T extends Record<string, unknown>, U extends Record<string, unknown>>(
|
|
74
|
+
target: T,
|
|
75
|
+
source: U
|
|
76
|
+
): T & U {
|
|
77
|
+
const result: Record<string, unknown> = {};
|
|
78
|
+
|
|
79
|
+
// Copy all target keys
|
|
80
|
+
for (const key of Object.keys(target)) {
|
|
81
|
+
result[key] = deepClone(target[key]);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Merge source keys
|
|
85
|
+
for (const key of Object.keys(source)) {
|
|
86
|
+
const tVal = result[key];
|
|
87
|
+
const sVal = source[key];
|
|
88
|
+
|
|
89
|
+
if (
|
|
90
|
+
tVal !== null &&
|
|
91
|
+
tVal !== undefined &&
|
|
92
|
+
sVal !== null &&
|
|
93
|
+
sVal !== undefined &&
|
|
94
|
+
typeof tVal === 'object' &&
|
|
95
|
+
typeof sVal === 'object' &&
|
|
96
|
+
!Array.isArray(tVal) &&
|
|
97
|
+
!Array.isArray(sVal) &&
|
|
98
|
+
!(tVal instanceof Date) &&
|
|
99
|
+
!(tVal instanceof RegExp) &&
|
|
100
|
+
!(tVal instanceof Map) &&
|
|
101
|
+
!(tVal instanceof Set) &&
|
|
102
|
+
!(sVal instanceof Date) &&
|
|
103
|
+
!(sVal instanceof RegExp) &&
|
|
104
|
+
!(sVal instanceof Map) &&
|
|
105
|
+
!(sVal instanceof Set)
|
|
106
|
+
) {
|
|
107
|
+
result[key] = deepMerge(tVal as Record<string, unknown>, sVal as Record<string, unknown>);
|
|
108
|
+
} else {
|
|
109
|
+
result[key] = deepClone(sVal);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return result as T & U;
|
|
114
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 公共下载工具函数
|
|
3
|
+
* 统一 chartDownloadUtils.ts 和 ExportUtils.ts 中的重复逻辑
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// 定时器追踪,防止泄漏
|
|
7
|
+
const timers: ReturnType<typeof setTimeout>[] = [];
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* 清除所有追踪的定时器
|
|
11
|
+
*/
|
|
12
|
+
export function clearAllTimers(): void {
|
|
13
|
+
timers.forEach(clearTimeout);
|
|
14
|
+
timers.length = 0;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* 生成默认文件名
|
|
19
|
+
* @param prefix 文件名前缀
|
|
20
|
+
* @returns 带时间戳的文件名
|
|
21
|
+
*/
|
|
22
|
+
export function generateFilename(prefix: string = 'chart'): string {
|
|
23
|
+
const timestamp = new Date().toISOString().slice(0, 19).replace(/[:-]/g, '');
|
|
24
|
+
return `${prefix}_${timestamp}`;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* 生成带格式的文件名
|
|
29
|
+
* @param name 文件名
|
|
30
|
+
* @param format 文件格式
|
|
31
|
+
* @returns 格式化的文件名
|
|
32
|
+
*/
|
|
33
|
+
export function generateFormattedFilename(name: string, format: string): string {
|
|
34
|
+
const timestamp = new Date().toISOString().slice(0, 10);
|
|
35
|
+
const sanitizedName = name.replace(/[^a-zA-Z0-9\u4e00-\u9fa5]/g, '_');
|
|
36
|
+
return `${sanitizedName}_${timestamp}.${format}`;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* 触发浏览器下载的通用函数
|
|
41
|
+
* @param href 下载链接
|
|
42
|
+
* @param filename 文件名
|
|
43
|
+
* @param cleanup 可选的清理回调(如 revokeObjectURL)
|
|
44
|
+
*/
|
|
45
|
+
function triggerDownload(href: string, filename: string, cleanup?: () => void): void {
|
|
46
|
+
if (typeof document === 'undefined') return;
|
|
47
|
+
const link = document.createElement('a');
|
|
48
|
+
link.href = href;
|
|
49
|
+
link.download = filename;
|
|
50
|
+
link.style.display = 'none';
|
|
51
|
+
document.body.appendChild(link);
|
|
52
|
+
link.click();
|
|
53
|
+
const timerId = setTimeout(() => {
|
|
54
|
+
if (link.parentNode) document.body.removeChild(link);
|
|
55
|
+
cleanup?.();
|
|
56
|
+
// Auto-remove from timers array
|
|
57
|
+
const idx = timers.indexOf(timerId);
|
|
58
|
+
if (idx !== -1) timers.splice(idx, 1);
|
|
59
|
+
}, 100);
|
|
60
|
+
timers.push(timerId);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* 下载 Blob 对象
|
|
65
|
+
* @param blob Blob 数据
|
|
66
|
+
* @param filename 文件名
|
|
67
|
+
*/
|
|
68
|
+
export function downloadBlob(blob: Blob, filename: string): void {
|
|
69
|
+
const url = URL.createObjectURL(blob);
|
|
70
|
+
triggerDownload(url, filename, () => URL.revokeObjectURL(url));
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* 下载数据 URL
|
|
75
|
+
* @param dataUrl 数据 URL
|
|
76
|
+
* @param filename 文件名
|
|
77
|
+
*/
|
|
78
|
+
export function downloadDataUrl(dataUrl: string, filename: string): void {
|
|
79
|
+
triggerDownload(dataUrl, filename);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* 下载文件(支持 string | Blob)
|
|
84
|
+
* @param data 数据(string 或 Blob)
|
|
85
|
+
* @param filename 文件名
|
|
86
|
+
* @param mimeType MIME 类型(仅当 data 为 string 时使用)
|
|
87
|
+
*/
|
|
88
|
+
export function downloadFile(data: string | Blob, filename: string, _mimeType?: string): void {
|
|
89
|
+
const blob =
|
|
90
|
+
typeof data === 'string' ? new Blob([data], { type: _mimeType || 'text/plain' }) : data;
|
|
91
|
+
downloadBlob(blob, filename);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* DataURL 转 Blob
|
|
96
|
+
* @param dataUrl 数据 URL
|
|
97
|
+
* @returns Blob 对象
|
|
98
|
+
*/
|
|
99
|
+
export function dataURLToBlob(dataUrl: string): Blob {
|
|
100
|
+
const arr = dataUrl.split(',');
|
|
101
|
+
const mimeMatch = arr[0].match(/:(.*?);/);
|
|
102
|
+
const mime = mimeMatch ? mimeMatch[1] : 'image/png';
|
|
103
|
+
const bstr = atob(arr[1]);
|
|
104
|
+
const n = bstr.length;
|
|
105
|
+
const u8arr = new Uint8Array(n);
|
|
106
|
+
for (let i = 0; i < n; i++) {
|
|
107
|
+
u8arr[i] = bstr.charCodeAt(i);
|
|
108
|
+
}
|
|
109
|
+
return new Blob([u8arr], { type: mime });
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* CSV 转 Blob
|
|
114
|
+
* @param csv CSV 字符串
|
|
115
|
+
* @returns Blob 对象
|
|
116
|
+
*/
|
|
117
|
+
export function csvToBlob(csv: string): Blob {
|
|
118
|
+
return new Blob([csv], { type: 'text/csv;charset=utf-8;' });
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* JSON 转 Blob
|
|
123
|
+
* @param json JSON 字符串
|
|
124
|
+
* @returns Blob 对象
|
|
125
|
+
*/
|
|
126
|
+
export function jsonToBlob(json: string): Blob {
|
|
127
|
+
return new Blob([json], { type: 'application/json;charset=utf-8;' });
|
|
128
|
+
}
|