bi-sdk-react 0.0.76 → 0.0.77
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/dist/es/js/bi-sdk.es.js +433 -46
- package/dist/es/js/bi-sdk.es.js.LICENSE.txt +15 -0
- package/dist/types/components/plugins/@antd/item-props/EchartsProps.d.ts +2 -0
- package/dist/types/components/plugins/@antd/item-props/SelectProps.d.ts +2 -0
- package/dist/types/components/plugins/@antd/items/SelectRender.d.ts +2 -0
- package/dist/umd/js/bi-sdk.umd.min.js +439 -52
- package/dist/umd/js/bi-sdk.umd.min.js.LICENSE.txt +15 -0
- package/package.json +1 -1
- package/src/components/plugins/@antd/index.ts +2 -0
- package/src/components/plugins/@antd/item-props/EchartsProps.tsx +1471 -46
- package/src/components/plugins/@antd/item-props/SelectProps.tsx +174 -13
- package/src/components/plugins/@antd/items/SelectRender.tsx +52 -3
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from "react";
|
|
1
|
+
import React, { useRef, useState } from "react";
|
|
2
2
|
import {
|
|
3
3
|
Form,
|
|
4
4
|
Input,
|
|
@@ -8,9 +8,18 @@ import {
|
|
|
8
8
|
Button,
|
|
9
9
|
Space,
|
|
10
10
|
type SelectProps as AntSelectProps,
|
|
11
|
+
Tooltip,
|
|
12
|
+
Drawer,
|
|
13
|
+
Flex,
|
|
11
14
|
} from "antd";
|
|
12
15
|
import type { PropEditorProps } from "./types";
|
|
13
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
DeleteOutlined,
|
|
18
|
+
FullscreenOutlined,
|
|
19
|
+
InfoCircleOutlined,
|
|
20
|
+
} from "@ant-design/icons";
|
|
21
|
+
import { IconFont } from "../../../icon/IconFont";
|
|
22
|
+
import { Editor } from "@monaco-editor/react";
|
|
14
23
|
|
|
15
24
|
export type SelectOption = { label: string; value: any };
|
|
16
25
|
export type SelectModel = {
|
|
@@ -19,6 +28,8 @@ export type SelectModel = {
|
|
|
19
28
|
size?: AntSelectProps["size"];
|
|
20
29
|
allowClear?: boolean;
|
|
21
30
|
multiple?: boolean;
|
|
31
|
+
source?: "local" | "script";
|
|
32
|
+
globalDatasetScript?: string;
|
|
22
33
|
options: SelectOption[];
|
|
23
34
|
};
|
|
24
35
|
|
|
@@ -26,6 +37,9 @@ export const SelectProps: React.FC<PropEditorProps<SelectModel>> = ({
|
|
|
26
37
|
model,
|
|
27
38
|
onChange,
|
|
28
39
|
}) => {
|
|
40
|
+
const ref = useRef<any>(null);
|
|
41
|
+
const fullRef = useRef<any>(null);
|
|
42
|
+
const [fullScreen, setFullScreen] = useState(false);
|
|
29
43
|
const trigger = (key: keyof SelectModel, value: any) =>
|
|
30
44
|
onChange && onChange({ ...model, [key]: value });
|
|
31
45
|
const setOption = (index: number, key: keyof SelectOption, value: any) => {
|
|
@@ -41,6 +55,16 @@ export const SelectProps: React.FC<PropEditorProps<SelectModel>> = ({
|
|
|
41
55
|
const addOption = () => {
|
|
42
56
|
trigger("options", [...(model.options || []), { label: "", value: "" }]);
|
|
43
57
|
};
|
|
58
|
+
const format = () => {
|
|
59
|
+
// Monaco-react does not expose format directly; relying on editor action
|
|
60
|
+
const editor = (ref.current as any)?.editor;
|
|
61
|
+
editor?.getAction("editor.action.formatDocument")?.run();
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const fullFormat = () => {
|
|
65
|
+
const editor = (fullRef.current as any)?.editor;
|
|
66
|
+
editor?.getAction("editor.action.formatDocument")?.run();
|
|
67
|
+
};
|
|
44
68
|
const columns = [
|
|
45
69
|
{
|
|
46
70
|
title: "选项标签",
|
|
@@ -118,19 +142,156 @@ export const SelectProps: React.FC<PropEditorProps<SelectModel>> = ({
|
|
|
118
142
|
onChange={(v) => trigger("multiple", v)}
|
|
119
143
|
/>
|
|
120
144
|
</Form.Item>
|
|
121
|
-
<Form.Item
|
|
122
|
-
<
|
|
145
|
+
<Form.Item label="数据来源">
|
|
146
|
+
<Radio.Group
|
|
123
147
|
size="small"
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
<Button size="small" block onClick={addOption}>
|
|
131
|
-
添加选项
|
|
132
|
-
</Button>
|
|
148
|
+
value={model.source || "local"}
|
|
149
|
+
onChange={(e) => trigger("source", e.target.value)}
|
|
150
|
+
>
|
|
151
|
+
<Radio.Button value="local">本地选项</Radio.Button>
|
|
152
|
+
<Radio.Button value="script">JS 脚本</Radio.Button>
|
|
153
|
+
</Radio.Group>
|
|
133
154
|
</Form.Item>
|
|
155
|
+
{model.source === "script" && (
|
|
156
|
+
<Form.Item
|
|
157
|
+
layout="vertical"
|
|
158
|
+
labelCol={{ span: 24 }}
|
|
159
|
+
wrapperCol={{ span: 24 }}
|
|
160
|
+
label={
|
|
161
|
+
<>
|
|
162
|
+
<Space>
|
|
163
|
+
JS 脚本{" "}
|
|
164
|
+
<Tooltip
|
|
165
|
+
title={
|
|
166
|
+
<>
|
|
167
|
+
模板语法参考
|
|
168
|
+
<ul style={{ padding: 0, listStyle: "none" }}>
|
|
169
|
+
<li>变量调用:{`{{变量名}}`}</li>
|
|
170
|
+
<li>全局变量:{`{{$g.变量名}}`}</li>
|
|
171
|
+
<li>返回值:{`return {label: string, value: string|number}[]`}</li>
|
|
172
|
+
</ul>
|
|
173
|
+
</>
|
|
174
|
+
}
|
|
175
|
+
>
|
|
176
|
+
<InfoCircleOutlined />
|
|
177
|
+
</Tooltip>
|
|
178
|
+
</Space>
|
|
179
|
+
<Space>
|
|
180
|
+
<a onClick={() => setFullScreen(true)}>
|
|
181
|
+
<FullscreenOutlined /> 全屏
|
|
182
|
+
</a>
|
|
183
|
+
<a onClick={format}>
|
|
184
|
+
<IconFont type="icon-formate" /> 格式化
|
|
185
|
+
</a>
|
|
186
|
+
</Space>
|
|
187
|
+
</>
|
|
188
|
+
}
|
|
189
|
+
className="ant-form-item-label-space"
|
|
190
|
+
>
|
|
191
|
+
<div
|
|
192
|
+
style={{
|
|
193
|
+
border: "1px solid #d9d9d9",
|
|
194
|
+
borderRadius: 4,
|
|
195
|
+
textAlign: "left",
|
|
196
|
+
}}
|
|
197
|
+
>
|
|
198
|
+
<div
|
|
199
|
+
style={{
|
|
200
|
+
color: "#0000ff",
|
|
201
|
+
fontSize: 14,
|
|
202
|
+
padding: "0 50px",
|
|
203
|
+
}}
|
|
204
|
+
>
|
|
205
|
+
function getOptions(data) {"{"}{" "}
|
|
206
|
+
</div>
|
|
207
|
+
<Editor
|
|
208
|
+
onMount={(editor) => {
|
|
209
|
+
(ref.current as any) = { editor };
|
|
210
|
+
}}
|
|
211
|
+
height="400px"
|
|
212
|
+
defaultLanguage="javascript"
|
|
213
|
+
value={model.globalDatasetScript}
|
|
214
|
+
onChange={(v) => trigger("globalDatasetScript", v || "")}
|
|
215
|
+
options={{
|
|
216
|
+
minimap: { enabled: false },
|
|
217
|
+
scrollBeyondLastLine: false,
|
|
218
|
+
tabSize: 2,
|
|
219
|
+
}}
|
|
220
|
+
/>
|
|
221
|
+
<div
|
|
222
|
+
style={{
|
|
223
|
+
color: "#0000ff",
|
|
224
|
+
fontSize: 14,
|
|
225
|
+
padding: "0 50px",
|
|
226
|
+
}}
|
|
227
|
+
>
|
|
228
|
+
{"}"}
|
|
229
|
+
</div>
|
|
230
|
+
</div>
|
|
231
|
+
</Form.Item>
|
|
232
|
+
)}
|
|
233
|
+
{model.source !== "script" && (
|
|
234
|
+
<Form.Item labelCol={{ span: 24 }} wrapperCol={{ span: 24 }}>
|
|
235
|
+
<Table
|
|
236
|
+
size="small"
|
|
237
|
+
dataSource={model.options}
|
|
238
|
+
columns={columns as any}
|
|
239
|
+
pagination={false}
|
|
240
|
+
rowKey={(_, i) => String(i)}
|
|
241
|
+
bordered
|
|
242
|
+
/>
|
|
243
|
+
<Button size="small" block onClick={addOption}>
|
|
244
|
+
添加选项
|
|
245
|
+
</Button>
|
|
246
|
+
</Form.Item>
|
|
247
|
+
)}
|
|
248
|
+
<Drawer
|
|
249
|
+
title={
|
|
250
|
+
<Flex justify="space-between" align="center">
|
|
251
|
+
JS 脚本
|
|
252
|
+
<Space>
|
|
253
|
+
<a key="format" onClick={fullFormat}>
|
|
254
|
+
<IconFont type="icon-formate" /> 格式化
|
|
255
|
+
</a>
|
|
256
|
+
</Space>
|
|
257
|
+
</Flex>
|
|
258
|
+
}
|
|
259
|
+
open={fullScreen}
|
|
260
|
+
width="100%"
|
|
261
|
+
onClose={() => setFullScreen(false)}
|
|
262
|
+
styles={{
|
|
263
|
+
body: {
|
|
264
|
+
padding: 0,
|
|
265
|
+
},
|
|
266
|
+
}}
|
|
267
|
+
>
|
|
268
|
+
<div
|
|
269
|
+
style={{
|
|
270
|
+
textAlign: "left",
|
|
271
|
+
}}
|
|
272
|
+
>
|
|
273
|
+
<div style={{ color: "#0000ff", fontSize: 14, padding: "0 50px" }}>
|
|
274
|
+
function getOptions(data) {"{"}{" "}
|
|
275
|
+
</div>
|
|
276
|
+
<Editor
|
|
277
|
+
onMount={(editor) => {
|
|
278
|
+
(fullRef.current as any) = { editor };
|
|
279
|
+
}}
|
|
280
|
+
height="calc(100vh - 100px)"
|
|
281
|
+
defaultLanguage="javascript"
|
|
282
|
+
value={model.globalDatasetScript}
|
|
283
|
+
onChange={(v) => trigger("globalDatasetScript", v || "")}
|
|
284
|
+
options={{
|
|
285
|
+
minimap: { enabled: false },
|
|
286
|
+
scrollBeyondLastLine: false,
|
|
287
|
+
tabSize: 2,
|
|
288
|
+
}}
|
|
289
|
+
/>
|
|
290
|
+
<div style={{ color: "#0000ff", fontSize: 14, padding: "0 50px" }}>
|
|
291
|
+
{"}"}
|
|
292
|
+
</div>
|
|
293
|
+
</div>
|
|
294
|
+
</Drawer>
|
|
134
295
|
</Form>
|
|
135
296
|
);
|
|
136
297
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Select, type SelectProps } from "antd";
|
|
2
|
-
import React, { useContext } from "react";
|
|
2
|
+
import React, { useContext, useMemo } from "react";
|
|
3
3
|
import { PageContext } from "../../../context/PageContext";
|
|
4
4
|
import { HtmlBaseProps, SchemaItemType } from "../../../typing";
|
|
5
5
|
import { useEvent } from "../../../hooks/event";
|
|
@@ -10,6 +10,8 @@ export type SelectRenderProps = {
|
|
|
10
10
|
placeholder?: string;
|
|
11
11
|
allowClear?: boolean;
|
|
12
12
|
multiple?: boolean;
|
|
13
|
+
source?: "local" | "script";
|
|
14
|
+
globalDatasetScript?: string;
|
|
13
15
|
options?: { label: string; value: any }[];
|
|
14
16
|
item: SchemaItemType;
|
|
15
17
|
value?: any;
|
|
@@ -23,6 +25,8 @@ export const SelectRender: React.FC<SelectRenderProps> = ({
|
|
|
23
25
|
placeholder = "请选择",
|
|
24
26
|
allowClear = false,
|
|
25
27
|
multiple = false,
|
|
28
|
+
source = "local",
|
|
29
|
+
globalDatasetScript = "",
|
|
26
30
|
options = [],
|
|
27
31
|
item,
|
|
28
32
|
value,
|
|
@@ -30,7 +34,7 @@ export const SelectRender: React.FC<SelectRenderProps> = ({
|
|
|
30
34
|
style = {},
|
|
31
35
|
className,
|
|
32
36
|
}) => {
|
|
33
|
-
const { handleCallback, setVar } = useContext(PageContext);
|
|
37
|
+
const { handleCallback, setVar, globalVars } = useContext(PageContext);
|
|
34
38
|
const { handleEvent } = useEvent(item);
|
|
35
39
|
const change = (v: any) => {
|
|
36
40
|
if (onChange) onChange(v);
|
|
@@ -38,6 +42,51 @@ export const SelectRender: React.FC<SelectRenderProps> = ({
|
|
|
38
42
|
handleCallback(item);
|
|
39
43
|
handleEvent("change", v);
|
|
40
44
|
};
|
|
45
|
+
|
|
46
|
+
const computedOptions = useMemo(() => {
|
|
47
|
+
if (source === "script") {
|
|
48
|
+
try {
|
|
49
|
+
const safeEval = new Function(
|
|
50
|
+
"console",
|
|
51
|
+
"Math",
|
|
52
|
+
"Date",
|
|
53
|
+
"Array",
|
|
54
|
+
"Object",
|
|
55
|
+
"String",
|
|
56
|
+
"Number",
|
|
57
|
+
"Boolean",
|
|
58
|
+
"$g",
|
|
59
|
+
`
|
|
60
|
+
"use strict";
|
|
61
|
+
const window = undefined;
|
|
62
|
+
const document = undefined;
|
|
63
|
+
const global = undefined;
|
|
64
|
+
const process = undefined;
|
|
65
|
+
const require = undefined;
|
|
66
|
+
const module = undefined;
|
|
67
|
+
const exports = undefined;
|
|
68
|
+
${globalDatasetScript}
|
|
69
|
+
`,
|
|
70
|
+
);
|
|
71
|
+
return safeEval(
|
|
72
|
+
console,
|
|
73
|
+
Math,
|
|
74
|
+
Date,
|
|
75
|
+
Array,
|
|
76
|
+
Object,
|
|
77
|
+
String,
|
|
78
|
+
Number,
|
|
79
|
+
Boolean,
|
|
80
|
+
globalVars,
|
|
81
|
+
);
|
|
82
|
+
} catch (error) {
|
|
83
|
+
console.error("Options 脚本执行错误", error);
|
|
84
|
+
return [];
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return options;
|
|
88
|
+
}, [source, options, globalVars]);
|
|
89
|
+
|
|
41
90
|
return (
|
|
42
91
|
<Select
|
|
43
92
|
id={id}
|
|
@@ -46,7 +95,7 @@ export const SelectRender: React.FC<SelectRenderProps> = ({
|
|
|
46
95
|
placeholder={placeholder}
|
|
47
96
|
allowClear={allowClear}
|
|
48
97
|
mode={multiple ? "multiple" : undefined}
|
|
49
|
-
options={
|
|
98
|
+
options={computedOptions}
|
|
50
99
|
onChange={change}
|
|
51
100
|
style={{ width: "100%", ...style }}
|
|
52
101
|
className={className}
|