bi-sdk-react 0.0.3 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/es/css/bi-sdk.css +1 -1
- package/dist/es/js/bi-sdk.es.js +295 -67
- package/dist/types/components/PageDesigner.d.ts +9 -1
- package/dist/types/components/context/DesignerContext.d.ts +5 -2
- package/dist/types/components/context/EnvContext.d.ts +2 -1
- package/dist/types/components/icon/IconFont.d.ts +2 -1
- package/dist/types/components/layout/PageCanvas.d.ts +2 -0
- package/dist/types/components/panel/AiPanel.d.ts +4 -0
- package/dist/types/components/panel/ChatInput.d.ts +13 -6
- package/dist/types/components/panel/DatasetPanel.d.ts +11 -0
- package/dist/types/components/panel/PaneHeader.d.ts +1 -0
- package/dist/types/components/panel/PropertiesPanel.d.ts +3 -1
- package/dist/types/components/plugins/@antd/item-props/CheckboxProps.d.ts +3 -3
- package/dist/types/components/plugins/@antd/item-props/ColProps.d.ts +2 -2
- package/dist/types/components/plugins/@antd/item-props/EchartsProps.d.ts +2 -2
- package/dist/types/components/plugins/@antd/item-props/TextProps.d.ts +1 -0
- package/dist/types/components/plugins/@antd/items/TableRender.d.ts +1 -0
- package/dist/types/components/plugins/@antd/items/TextRender.d.ts +1 -0
- package/dist/types/components/typing.d.ts +97 -2
- package/dist/types/components/utils.d.ts +1 -0
- package/dist/umd/css/bi-sdk.css +1 -1
- package/dist/umd/js/bi-sdk.umd.min.js +299 -71
- package/package.json +1 -1
- package/src/components/PageDesigner.tsx +293 -35
- package/src/components/context/DesignerContext.tsx +15 -3
- package/src/components/context/EnvContext.tsx +4 -1
- package/src/components/icon/IconFont.tsx +15 -11
- package/src/components/layout/PageCanvas.tsx +4 -2
- package/src/components/layout/PageItem.tsx +1 -1
- package/src/components/panel/AiPanel.tsx +609 -43
- package/src/components/panel/ChatInput.tsx +322 -180
- package/src/components/panel/DatasetPanel.tsx +65 -0
- package/src/components/panel/PaneHeader.tsx +3 -2
- package/src/components/panel/PropertiesPanel.tsx +334 -127
- package/src/components/plugins/@antd/index.ts +12 -9
- package/src/components/plugins/@antd/item-props/CapsuleProps.tsx +1 -1
- package/src/components/plugins/@antd/item-props/CheckboxProps.tsx +90 -42
- package/src/components/plugins/@antd/item-props/ColProps.tsx +139 -25
- package/src/components/plugins/@antd/item-props/EchartsProps.tsx +52 -22
- package/src/components/plugins/@antd/item-props/HtmlProps.tsx +8 -9
- package/src/components/plugins/@antd/item-props/SelectProps.tsx +1 -1
- package/src/components/plugins/@antd/item-props/TextProps.tsx +14 -3
- package/src/components/plugins/@antd/items/EchartsRender.tsx +9 -1
- package/src/components/plugins/@antd/items/HtmlRender.tsx +13 -1
- package/src/components/plugins/@antd/items/ListRender.tsx +18 -1
- package/src/components/plugins/@antd/items/TableRender.tsx +16 -1
- package/src/components/plugins/@antd/items/TextRender.tsx +3 -1
- package/src/components/styles.css +20 -0
- package/src/components/typing.ts +111 -2
- package/src/components/utils.ts +40 -0
- package/src/example.tsx +314 -13
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { Space } from "antd";
|
|
2
|
+
import React, { forwardRef, useImperativeHandle, useRef } from "react";
|
|
3
|
+
import styled from "styled-components";
|
|
4
|
+
import { PaneHeader } from "./PaneHeader";
|
|
5
|
+
|
|
6
|
+
const Root = styled.div`
|
|
7
|
+
display: flex;
|
|
8
|
+
flex-direction: column;
|
|
9
|
+
height: 100%;
|
|
10
|
+
.body {
|
|
11
|
+
flex: 1 1 auto;
|
|
12
|
+
display: flex;
|
|
13
|
+
flex-direction: column;
|
|
14
|
+
gap: 12px;
|
|
15
|
+
padding: 12px;
|
|
16
|
+
overflow: auto;
|
|
17
|
+
}
|
|
18
|
+
`;
|
|
19
|
+
|
|
20
|
+
type DatasetPanelType = {
|
|
21
|
+
renderNode: React.ForwardRefExoticComponent<
|
|
22
|
+
any &
|
|
23
|
+
React.RefAttributes<{
|
|
24
|
+
reload: () => void;
|
|
25
|
+
handleAdd: () => void;
|
|
26
|
+
}>
|
|
27
|
+
>;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const DatasetPanel = React.forwardRef<
|
|
31
|
+
{ reload: () => void },
|
|
32
|
+
DatasetPanelType
|
|
33
|
+
>(({ renderNode: DatasetPanelComponent }, forwardRef) => {
|
|
34
|
+
const ref = useRef<{ reload: () => void; handleAdd: () => void }>(null);
|
|
35
|
+
|
|
36
|
+
const handleAdd = () => {
|
|
37
|
+
ref.current?.handleAdd();
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
useImperativeHandle(forwardRef, () => ({
|
|
41
|
+
reload,
|
|
42
|
+
}));
|
|
43
|
+
|
|
44
|
+
const reload = () => {
|
|
45
|
+
ref.current?.reload();
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<Root className="dataset-panel">
|
|
50
|
+
<PaneHeader
|
|
51
|
+
title="数据集"
|
|
52
|
+
extra={
|
|
53
|
+
<Space>
|
|
54
|
+
<a className="toolbar" onClick={handleAdd}>
|
|
55
|
+
+
|
|
56
|
+
</a>
|
|
57
|
+
</Space>
|
|
58
|
+
}
|
|
59
|
+
/>
|
|
60
|
+
<div className="body">
|
|
61
|
+
<DatasetPanelComponent ref={ref} />
|
|
62
|
+
</div>
|
|
63
|
+
</Root>
|
|
64
|
+
);
|
|
65
|
+
});
|
|
@@ -4,6 +4,7 @@ import styled from 'styled-components'
|
|
|
4
4
|
export type PaneHeaderProps = {
|
|
5
5
|
title?: string
|
|
6
6
|
extra?: React.ReactNode
|
|
7
|
+
style?: React.CSSProperties
|
|
7
8
|
}
|
|
8
9
|
|
|
9
10
|
const Header = styled.div`
|
|
@@ -24,9 +25,9 @@ const Header = styled.div`
|
|
|
24
25
|
}
|
|
25
26
|
`
|
|
26
27
|
|
|
27
|
-
export const PaneHeader: React.FC<PaneHeaderProps> = ({ title = '', extra }) => {
|
|
28
|
+
export const PaneHeader: React.FC<PaneHeaderProps> = ({ title = '', extra, style = {} }) => {
|
|
28
29
|
return (
|
|
29
|
-
<Header className="pane-header">
|
|
30
|
+
<Header className="pane-header" style={style}>
|
|
30
31
|
<span className="title">{title}</span>
|
|
31
32
|
<div className="extra">{extra}</div>
|
|
32
33
|
</Header>
|
|
@@ -1,11 +1,28 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CloseOutlined,
|
|
3
|
+
DeleteOutlined,
|
|
4
|
+
InboxOutlined,
|
|
5
|
+
SelectOutlined,
|
|
6
|
+
} from "@ant-design/icons";
|
|
7
|
+
import Editor from "@monaco-editor/react";
|
|
8
|
+
import {
|
|
9
|
+
Button,
|
|
10
|
+
Divider,
|
|
11
|
+
Drawer,
|
|
12
|
+
Form,
|
|
13
|
+
Input,
|
|
14
|
+
Popover,
|
|
15
|
+
Radio,
|
|
16
|
+
Select,
|
|
17
|
+
Space,
|
|
18
|
+
Upload,
|
|
19
|
+
} from "antd";
|
|
1
20
|
import React, { useContext, useMemo, useRef, useState } from "react";
|
|
2
21
|
import styled from "styled-components";
|
|
3
|
-
import { PaneHeader } from "./PaneHeader";
|
|
4
|
-
import { Radio, Divider, Form, Input, Upload, Button, Select } from "antd";
|
|
5
|
-
import Editor from "@monaco-editor/react";
|
|
6
|
-
import { InboxOutlined, DeleteOutlined } from "@ant-design/icons";
|
|
7
|
-
import { IconFont } from "../icon/IconFont";
|
|
8
22
|
import { DesignerContext } from "../context/DesignerContext";
|
|
23
|
+
import { IconFont } from "../icon/IconFont";
|
|
24
|
+
import { PaneHeader } from "./PaneHeader";
|
|
25
|
+
import { DataSetOutput, SchemaItemType, FieldType } from "../typing";
|
|
9
26
|
|
|
10
27
|
const Root = styled.div`
|
|
11
28
|
display: flex;
|
|
@@ -19,12 +36,12 @@ const Root = styled.div`
|
|
|
19
36
|
padding: 12px;
|
|
20
37
|
overflow: auto;
|
|
21
38
|
|
|
39
|
+
.ant-form-item {
|
|
40
|
+
margin-bottom: 8px;
|
|
41
|
+
}
|
|
42
|
+
|
|
22
43
|
.ant-form-item-label {
|
|
23
44
|
text-align: left;
|
|
24
|
-
|
|
25
|
-
label {
|
|
26
|
-
display: inline;
|
|
27
|
-
}
|
|
28
45
|
}
|
|
29
46
|
|
|
30
47
|
.ant-form-item-control-input,
|
|
@@ -32,6 +49,10 @@ const Root = styled.div`
|
|
|
32
49
|
text-align: end;
|
|
33
50
|
justify-content: flex-end;
|
|
34
51
|
}
|
|
52
|
+
|
|
53
|
+
.ant-divider {
|
|
54
|
+
margin: 0;
|
|
55
|
+
}
|
|
35
56
|
}
|
|
36
57
|
`;
|
|
37
58
|
|
|
@@ -51,8 +72,17 @@ const computeItems = (rootItems: any[] = []) => {
|
|
|
51
72
|
return items;
|
|
52
73
|
};
|
|
53
74
|
|
|
54
|
-
export const PropertiesPanel: React.FC
|
|
55
|
-
|
|
75
|
+
export const PropertiesPanel: React.FC<{
|
|
76
|
+
datasourceEnable?: boolean;
|
|
77
|
+
}> = ({ datasourceEnable = true }) => {
|
|
78
|
+
const {
|
|
79
|
+
plugins,
|
|
80
|
+
selectedItem,
|
|
81
|
+
updateSelectedItem: onUpdateSelectedItem,
|
|
82
|
+
schema,
|
|
83
|
+
setSchema,
|
|
84
|
+
datasetSelector,
|
|
85
|
+
} = useContext(DesignerContext);
|
|
56
86
|
const refCustomDatasource = useRef<any>(null);
|
|
57
87
|
const [selectedTab, setSelectedTab] = useState<"1" | "2">("1");
|
|
58
88
|
const items = useMemo(() => computeItems(schema?.items || []), [schema]);
|
|
@@ -76,9 +106,11 @@ export const PropertiesPanel: React.FC = () => {
|
|
|
76
106
|
onUpdateSelectedItem({ ...selectedItem, props: next });
|
|
77
107
|
};
|
|
78
108
|
const [reportForm, setReportForm] = useState<any>(schema?.info || {});
|
|
79
|
-
const [datasource, setDatasource] = useState<
|
|
109
|
+
const [datasource, setDatasource] = useState<SchemaItemType["datasource"]>(
|
|
80
110
|
selectedItem?.datasource || {}
|
|
81
111
|
);
|
|
112
|
+
const [datasetSelectorOpen, setDatasetSelectorOpen] =
|
|
113
|
+
useState<boolean>(false);
|
|
82
114
|
const onUpdateReportProps = (next: any) => {
|
|
83
115
|
setSchema({ ...schema, info: next });
|
|
84
116
|
};
|
|
@@ -126,7 +158,11 @@ export const PropertiesPanel: React.FC = () => {
|
|
|
126
158
|
/>
|
|
127
159
|
<div className="body">
|
|
128
160
|
{activeTab === "1" && (
|
|
129
|
-
<Form
|
|
161
|
+
<Form
|
|
162
|
+
labelCol={{ span: 24 }}
|
|
163
|
+
wrapperCol={{ span: 24 }}
|
|
164
|
+
className="ant-form-compact"
|
|
165
|
+
>
|
|
130
166
|
<Form.Item label="页面名称">
|
|
131
167
|
<Input
|
|
132
168
|
size="small"
|
|
@@ -194,11 +230,15 @@ export const PropertiesPanel: React.FC = () => {
|
|
|
194
230
|
{activeTab === "2" && (
|
|
195
231
|
<>
|
|
196
232
|
<Divider>基础属性</Divider>
|
|
197
|
-
<Form
|
|
233
|
+
<Form
|
|
234
|
+
labelCol={{ span: 24 }}
|
|
235
|
+
wrapperCol={{ span: 24 }}
|
|
236
|
+
className="ant-form-compact"
|
|
237
|
+
>
|
|
198
238
|
<Form.Item
|
|
199
239
|
label="组件标识"
|
|
200
|
-
labelCol={{ span:
|
|
201
|
-
wrapperCol={{ span:
|
|
240
|
+
labelCol={{ span: 5 }}
|
|
241
|
+
wrapperCol={{ span: 19 }}
|
|
202
242
|
>
|
|
203
243
|
{selectedItem?.id || ""}
|
|
204
244
|
</Form.Item>
|
|
@@ -231,7 +271,7 @@ export const PropertiesPanel: React.FC = () => {
|
|
|
231
271
|
</Form>
|
|
232
272
|
{selectedItem?.datasource && <Divider>数据源</Divider>}
|
|
233
273
|
{selectedItem?.datasource && (
|
|
234
|
-
<Form
|
|
274
|
+
<Form className="ant-form-compact">
|
|
235
275
|
<Form.Item
|
|
236
276
|
label={
|
|
237
277
|
<div
|
|
@@ -242,13 +282,125 @@ export const PropertiesPanel: React.FC = () => {
|
|
|
242
282
|
}}
|
|
243
283
|
>
|
|
244
284
|
数据来源
|
|
245
|
-
|
|
285
|
+
</div>
|
|
286
|
+
}
|
|
287
|
+
labelCol={{ span: 5 }}
|
|
288
|
+
wrapperCol={{ span: 19 }}
|
|
289
|
+
colon={false}
|
|
290
|
+
>
|
|
291
|
+
<Radio.Group
|
|
292
|
+
size="small"
|
|
293
|
+
value={datasource?.source}
|
|
294
|
+
onChange={(e) => {
|
|
295
|
+
const next = {
|
|
296
|
+
...(datasource || {}),
|
|
297
|
+
source: e.target.value,
|
|
298
|
+
};
|
|
299
|
+
setDatasource(next);
|
|
300
|
+
onUpdateSelectedItem &&
|
|
301
|
+
onUpdateSelectedItem({
|
|
302
|
+
...selectedItem,
|
|
303
|
+
datasource: next,
|
|
304
|
+
});
|
|
305
|
+
}}
|
|
306
|
+
>
|
|
307
|
+
{!!datasetSelector && (
|
|
308
|
+
<Radio.Button value="dataset">数据集</Radio.Button>
|
|
309
|
+
)}
|
|
310
|
+
{datasourceEnable && (
|
|
311
|
+
<Radio.Button value="define">数据源</Radio.Button>
|
|
312
|
+
)}
|
|
313
|
+
<Radio.Button value="custom">自定义</Radio.Button>
|
|
314
|
+
</Radio.Group>
|
|
315
|
+
</Form.Item>
|
|
316
|
+
{datasource?.source === "dataset" && datasetSelector && (
|
|
317
|
+
<>
|
|
318
|
+
<Form.Item
|
|
319
|
+
label="数据集"
|
|
320
|
+
labelCol={{ span: 5 }}
|
|
321
|
+
wrapperCol={{ span: 19 }}
|
|
322
|
+
>
|
|
323
|
+
<Space.Compact>
|
|
324
|
+
<Input
|
|
325
|
+
size="small"
|
|
326
|
+
readOnly={true}
|
|
327
|
+
value={datasource?.dataset?.name || ""}
|
|
328
|
+
style={{ width: 90 }}
|
|
329
|
+
/>
|
|
330
|
+
{!!datasource?.dataset?.id?.length && datasource?.dataset?.output && (
|
|
331
|
+
<Popover
|
|
332
|
+
title="输出类型"
|
|
333
|
+
placement="left"
|
|
334
|
+
content={
|
|
335
|
+
<div
|
|
336
|
+
style={{
|
|
337
|
+
padding: "0 12px",
|
|
338
|
+
maxWidth: 500,
|
|
339
|
+
maxHeight: 500,
|
|
340
|
+
overflow: "auto",
|
|
341
|
+
}}
|
|
342
|
+
>
|
|
343
|
+
<OutputTypePrint
|
|
344
|
+
output={datasource.dataset.output}
|
|
345
|
+
/>
|
|
346
|
+
</div>
|
|
347
|
+
}
|
|
348
|
+
>
|
|
349
|
+
<Button
|
|
350
|
+
size="small"
|
|
351
|
+
style={{
|
|
352
|
+
color: "var(--ant-color-text-tertiary)",
|
|
353
|
+
}}
|
|
354
|
+
title="查看输出类型"
|
|
355
|
+
>
|
|
356
|
+
<IconFont type="icon-json" />
|
|
357
|
+
</Button>
|
|
358
|
+
</Popover>
|
|
359
|
+
)}
|
|
360
|
+
{!!datasource?.dataset?.id?.length && (
|
|
361
|
+
<Button
|
|
362
|
+
size="small"
|
|
363
|
+
icon={<CloseOutlined />}
|
|
364
|
+
onClick={() => {
|
|
365
|
+
const next = {
|
|
366
|
+
...(datasource || {}),
|
|
367
|
+
dataset: {
|
|
368
|
+
id: "",
|
|
369
|
+
name: "",
|
|
370
|
+
output: { fields: [] },
|
|
371
|
+
},
|
|
372
|
+
};
|
|
373
|
+
setDatasource(next);
|
|
374
|
+
onUpdateSelectedItem &&
|
|
375
|
+
onUpdateSelectedItem({
|
|
376
|
+
...selectedItem,
|
|
377
|
+
datasource: next,
|
|
378
|
+
});
|
|
379
|
+
}}
|
|
380
|
+
title="删除数据集"
|
|
381
|
+
style={{ color: "var(--ant-color-text-tertiary)" }}
|
|
382
|
+
/>
|
|
383
|
+
)}
|
|
384
|
+
<Button
|
|
385
|
+
size="small"
|
|
386
|
+
icon={<SelectOutlined />}
|
|
387
|
+
title="选择数据集"
|
|
388
|
+
onClick={() => setDatasetSelectorOpen(true)}
|
|
389
|
+
/>
|
|
390
|
+
</Space.Compact>
|
|
391
|
+
</Form.Item>
|
|
392
|
+
</>
|
|
393
|
+
)}
|
|
394
|
+
{datasource?.source === "define" && (
|
|
395
|
+
<>
|
|
396
|
+
<Form.Item label="数据源" layout="vertical">
|
|
397
|
+
<Select
|
|
246
398
|
size="small"
|
|
247
|
-
value={datasource?.
|
|
248
|
-
onChange={(
|
|
399
|
+
value={datasource?.datasourceId}
|
|
400
|
+
onChange={(v) => {
|
|
249
401
|
const next = {
|
|
250
402
|
...(datasource || {}),
|
|
251
|
-
|
|
403
|
+
datasourceId: v,
|
|
252
404
|
};
|
|
253
405
|
setDatasource(next);
|
|
254
406
|
onUpdateSelectedItem &&
|
|
@@ -258,22 +410,83 @@ export const PropertiesPanel: React.FC = () => {
|
|
|
258
410
|
});
|
|
259
411
|
}}
|
|
260
412
|
>
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
413
|
+
{(schema?.datasources || []).map((item: any) => (
|
|
414
|
+
<Select.Option key={item.id} value={item.id}>
|
|
415
|
+
{item.name}
|
|
416
|
+
</Select.Option>
|
|
417
|
+
))}
|
|
418
|
+
</Select>
|
|
419
|
+
</Form.Item>
|
|
420
|
+
<Form.Item
|
|
421
|
+
label="数据处理脚本"
|
|
422
|
+
labelCol={{ span: 24 }}
|
|
423
|
+
wrapperCol={{ span: 24 }}
|
|
424
|
+
>
|
|
425
|
+
<Select
|
|
426
|
+
size="small"
|
|
427
|
+
value={datasource?.scriptId}
|
|
428
|
+
onChange={(v) => {
|
|
429
|
+
const next = { ...(datasource || {}), scriptId: v };
|
|
430
|
+
setDatasource(next);
|
|
431
|
+
onUpdateSelectedItem &&
|
|
432
|
+
onUpdateSelectedItem({
|
|
433
|
+
...selectedItem,
|
|
434
|
+
datasource: next,
|
|
435
|
+
});
|
|
436
|
+
}}
|
|
437
|
+
>
|
|
438
|
+
{(schema?.scripts || []).map((item: any) => (
|
|
439
|
+
<Select.Option key={item.id} value={item.id}>
|
|
440
|
+
{item.name}
|
|
441
|
+
</Select.Option>
|
|
442
|
+
))}
|
|
443
|
+
</Select>
|
|
444
|
+
</Form.Item>
|
|
445
|
+
</>
|
|
446
|
+
)}
|
|
447
|
+
{datasource?.source === "custom" && (
|
|
448
|
+
<>
|
|
449
|
+
<Form.Item
|
|
450
|
+
label={
|
|
451
|
+
<>
|
|
452
|
+
自定义
|
|
453
|
+
<a
|
|
454
|
+
onClick={() => {
|
|
455
|
+
/* formatting via Monaco action not exposed here */
|
|
456
|
+
const editor = (
|
|
457
|
+
refCustomDatasource.current as any
|
|
458
|
+
)?.editor;
|
|
459
|
+
editor
|
|
460
|
+
?.getAction("editor.action.formatDocument")
|
|
461
|
+
?.run();
|
|
462
|
+
}}
|
|
463
|
+
>
|
|
464
|
+
<IconFont type="icon-formate" /> 格式化
|
|
465
|
+
</a>
|
|
466
|
+
</>
|
|
467
|
+
}
|
|
468
|
+
labelCol={{ span: 24 }}
|
|
469
|
+
wrapperCol={{ span: 24 }}
|
|
470
|
+
className="ant-form-item-label-space"
|
|
471
|
+
>
|
|
472
|
+
<div
|
|
473
|
+
style={{
|
|
474
|
+
border: `1px solid var(--ant-color-border)`,
|
|
475
|
+
borderRadius: "var(--ant-border-radius)",
|
|
476
|
+
padding: 1,
|
|
477
|
+
}}
|
|
478
|
+
>
|
|
479
|
+
<Editor
|
|
480
|
+
height="200px"
|
|
481
|
+
onMount={(editor) => {
|
|
482
|
+
(refCustomDatasource.current as any) = { editor };
|
|
483
|
+
}}
|
|
484
|
+
defaultLanguage="json"
|
|
485
|
+
value={datasource?.custom || ""}
|
|
273
486
|
onChange={(v) => {
|
|
274
487
|
const next = {
|
|
275
488
|
...(datasource || {}),
|
|
276
|
-
|
|
489
|
+
custom: v || "",
|
|
277
490
|
};
|
|
278
491
|
setDatasource(next);
|
|
279
492
|
onUpdateSelectedItem &&
|
|
@@ -282,100 +495,16 @@ export const PropertiesPanel: React.FC = () => {
|
|
|
282
495
|
datasource: next,
|
|
283
496
|
});
|
|
284
497
|
}}
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
</Select.Option>
|
|
290
|
-
))}
|
|
291
|
-
</Select>
|
|
292
|
-
</Form.Item>
|
|
293
|
-
<Form.Item label="数据处理脚本" labelCol={{ span: 24 }} wrapperCol={{ span: 24 }}>
|
|
294
|
-
<Select
|
|
295
|
-
size="small"
|
|
296
|
-
value={datasource?.scriptId}
|
|
297
|
-
onChange={(v) => {
|
|
298
|
-
const next = { ...(datasource || {}), scriptId: v };
|
|
299
|
-
setDatasource(next);
|
|
300
|
-
onUpdateSelectedItem &&
|
|
301
|
-
onUpdateSelectedItem({
|
|
302
|
-
...selectedItem,
|
|
303
|
-
datasource: next,
|
|
304
|
-
});
|
|
305
|
-
}}
|
|
306
|
-
>
|
|
307
|
-
{(schema?.scripts || []).map((item: any) => (
|
|
308
|
-
<Select.Option key={item.id} value={item.id}>
|
|
309
|
-
{item.name}
|
|
310
|
-
</Select.Option>
|
|
311
|
-
))}
|
|
312
|
-
</Select>
|
|
313
|
-
</Form.Item>
|
|
314
|
-
</>
|
|
315
|
-
)}
|
|
316
|
-
{datasource?.source === "custom" && (
|
|
317
|
-
<>
|
|
318
|
-
<Form.Item
|
|
319
|
-
label={
|
|
320
|
-
<div
|
|
321
|
-
style={{
|
|
322
|
-
display: "flex",
|
|
323
|
-
alignItems: "center",
|
|
324
|
-
justifyContent: "space-between",
|
|
325
|
-
}}
|
|
326
|
-
>
|
|
327
|
-
自定义
|
|
328
|
-
<a
|
|
329
|
-
onClick={() => {
|
|
330
|
-
/* formatting via Monaco action not exposed here */
|
|
331
|
-
const editor = (refCustomDatasource.current as any)?.editor;
|
|
332
|
-
editor?.getAction("editor.action.formatDocument")?.run();
|
|
333
|
-
}}
|
|
334
|
-
>
|
|
335
|
-
<IconFont type="icon-formate" /> 格式化
|
|
336
|
-
</a>
|
|
337
|
-
</div>
|
|
338
|
-
}
|
|
339
|
-
labelCol={{ span: 24 }}
|
|
340
|
-
wrapperCol={{ span: 24 }}
|
|
341
|
-
>
|
|
342
|
-
<div
|
|
343
|
-
style={{
|
|
344
|
-
border: `1px solid var(--ant-color-border)`,
|
|
345
|
-
borderRadius: "var(--ant-border-radius)",
|
|
346
|
-
padding: 1,
|
|
498
|
+
options={{
|
|
499
|
+
minimap: { enabled: false },
|
|
500
|
+
scrollBeyondLastLine: false,
|
|
501
|
+
tabSize: 2,
|
|
347
502
|
}}
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
}}
|
|
354
|
-
defaultLanguage="json"
|
|
355
|
-
value={datasource?.custom}
|
|
356
|
-
onChange={(v) => {
|
|
357
|
-
const next = {
|
|
358
|
-
...(datasource || {}),
|
|
359
|
-
custom: v || "",
|
|
360
|
-
};
|
|
361
|
-
setDatasource(next);
|
|
362
|
-
onUpdateSelectedItem &&
|
|
363
|
-
onUpdateSelectedItem({
|
|
364
|
-
...selectedItem,
|
|
365
|
-
datasource: next,
|
|
366
|
-
});
|
|
367
|
-
}}
|
|
368
|
-
options={{
|
|
369
|
-
minimap: { enabled: false },
|
|
370
|
-
scrollBeyondLastLine: false,
|
|
371
|
-
tabSize: 2,
|
|
372
|
-
}}
|
|
373
|
-
/>
|
|
374
|
-
</div>
|
|
375
|
-
</Form.Item>
|
|
376
|
-
</>
|
|
377
|
-
)}
|
|
378
|
-
</Form.Item>
|
|
503
|
+
/>
|
|
504
|
+
</div>
|
|
505
|
+
</Form.Item>
|
|
506
|
+
</>
|
|
507
|
+
)}
|
|
379
508
|
</Form>
|
|
380
509
|
)}
|
|
381
510
|
{FormComp && <Divider>特有属性</Divider>}
|
|
@@ -389,6 +518,84 @@ export const PropertiesPanel: React.FC = () => {
|
|
|
389
518
|
</>
|
|
390
519
|
)}
|
|
391
520
|
</div>
|
|
521
|
+
|
|
522
|
+
{!!datasetSelector && (
|
|
523
|
+
<Drawer
|
|
524
|
+
title="选择数据集"
|
|
525
|
+
size={800}
|
|
526
|
+
open={datasetSelectorOpen}
|
|
527
|
+
onClose={() => {
|
|
528
|
+
setDatasetSelectorOpen(false);
|
|
529
|
+
}}
|
|
530
|
+
>
|
|
531
|
+
{datasetSelector((dataset) => {
|
|
532
|
+
datasource!.dataset = dataset;
|
|
533
|
+
setDatasetSelectorOpen(false);
|
|
534
|
+
})}
|
|
535
|
+
</Drawer>
|
|
536
|
+
)}
|
|
392
537
|
</Root>
|
|
393
538
|
);
|
|
394
539
|
};
|
|
540
|
+
|
|
541
|
+
const OutputTypePrint: React.FC<{
|
|
542
|
+
output: DataSetOutput;
|
|
543
|
+
}> = ({ output }) => {
|
|
544
|
+
const renderFields = (fields: DataSetOutput["fields"], indent = 0) => {
|
|
545
|
+
if (!fields || fields.length === 0) return <span>{"{}"}</span>;
|
|
546
|
+
|
|
547
|
+
return (
|
|
548
|
+
<>
|
|
549
|
+
{"{"}
|
|
550
|
+
{fields.map((field, index) => (
|
|
551
|
+
<div key={field.key || index} style={{ paddingLeft: "1em" }}>
|
|
552
|
+
<span style={{ color: "var(--ant-color-primary)" }}>
|
|
553
|
+
{field.key}
|
|
554
|
+
</span>
|
|
555
|
+
:{" "}
|
|
556
|
+
{field.type === FieldType.ARRAY ? (
|
|
557
|
+
<>
|
|
558
|
+
Array{"<"}
|
|
559
|
+
{field.schema ? (
|
|
560
|
+
renderFields(field.schema.fields, indent + 1)
|
|
561
|
+
) : (
|
|
562
|
+
<span>any</span>
|
|
563
|
+
)}
|
|
564
|
+
{">"}
|
|
565
|
+
</>
|
|
566
|
+
) : field.type === FieldType.OBJECT ? (
|
|
567
|
+
field.schema ? (
|
|
568
|
+
renderFields(field.schema.fields, indent + 1)
|
|
569
|
+
) : (
|
|
570
|
+
<span>{"{}"}</span>
|
|
571
|
+
)
|
|
572
|
+
) : (
|
|
573
|
+
<span style={{ color: "var(--ant-color-success)" }}>
|
|
574
|
+
{(field.type || "string").toLowerCase()}
|
|
575
|
+
</span>
|
|
576
|
+
)}
|
|
577
|
+
{index < fields.length - 1 ? "," : ""}
|
|
578
|
+
</div>
|
|
579
|
+
))}
|
|
580
|
+
{"}"}
|
|
581
|
+
</>
|
|
582
|
+
);
|
|
583
|
+
};
|
|
584
|
+
|
|
585
|
+
return (
|
|
586
|
+
<pre
|
|
587
|
+
style={{
|
|
588
|
+
margin: "8px 0",
|
|
589
|
+
padding: "8px",
|
|
590
|
+
background: "var(--ant-color-fill-alter)",
|
|
591
|
+
borderRadius: "var(--ant-border-radius-sm)",
|
|
592
|
+
fontSize: "12px",
|
|
593
|
+
fontFamily: "monospace",
|
|
594
|
+
overflowX: "auto",
|
|
595
|
+
border: "1px solid var(--ant-color-border-secondary)",
|
|
596
|
+
}}
|
|
597
|
+
>
|
|
598
|
+
{renderFields(output.fields)}
|
|
599
|
+
</pre>
|
|
600
|
+
);
|
|
601
|
+
};
|
|
@@ -53,15 +53,19 @@ export const TextPlugin: PluginType = {
|
|
|
53
53
|
component: TextRender,
|
|
54
54
|
formComponent: TextProps,
|
|
55
55
|
defaultOptions: {
|
|
56
|
-
style: {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
56
|
+
style: {},
|
|
57
|
+
props: {
|
|
58
|
+
text: "文本内容",
|
|
59
|
+
classNames: [],
|
|
60
|
+
customStyle: {
|
|
61
|
+
fontSize: 14,
|
|
62
|
+
color: "#444444",
|
|
63
|
+
fontFamily: "'宋体', 'SimSun', serif",
|
|
64
|
+
fontWeight: "normal",
|
|
65
|
+
fontStyle: "normal",
|
|
66
|
+
textDecoration: "none",
|
|
67
|
+
},
|
|
63
68
|
},
|
|
64
|
-
props: { text: "文本内容" },
|
|
65
69
|
},
|
|
66
70
|
};
|
|
67
71
|
|
|
@@ -184,7 +188,6 @@ export const HtmlPlugin: PluginType = {
|
|
|
184
188
|
custom: `{"name": "Confucius"}`,
|
|
185
189
|
},
|
|
186
190
|
props: {
|
|
187
|
-
dataSource: { name: "Confucius" },
|
|
188
191
|
template: `<div>{{name}}, welcome to the world of programming.</div>`,
|
|
189
192
|
},
|
|
190
193
|
},
|
|
@@ -84,7 +84,7 @@ export const CapsuleProps: React.FC<PropEditorProps<CapsuleModel>> = ({
|
|
|
84
84
|
<Radio.Button value="large">大</Radio.Button>
|
|
85
85
|
</Radio.Group>
|
|
86
86
|
</Form.Item>
|
|
87
|
-
<Form.Item>
|
|
87
|
+
<Form.Item labelCol={{ span: 24 }} wrapperCol={{ span: 24 }}>
|
|
88
88
|
<Table
|
|
89
89
|
size="small"
|
|
90
90
|
dataSource={model.options}
|