bi-sdk-react 0.0.4 → 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.
Files changed (45) hide show
  1. package/dist/es/css/bi-sdk.css +1 -1
  2. package/dist/es/js/bi-sdk.es.js +270 -63
  3. package/dist/types/components/PageDesigner.d.ts +9 -1
  4. package/dist/types/components/context/DesignerContext.d.ts +5 -2
  5. package/dist/types/components/context/EnvContext.d.ts +2 -1
  6. package/dist/types/components/icon/IconFont.d.ts +2 -1
  7. package/dist/types/components/layout/PageCanvas.d.ts +2 -0
  8. package/dist/types/components/panel/AiPanel.d.ts +4 -0
  9. package/dist/types/components/panel/ChatInput.d.ts +13 -6
  10. package/dist/types/components/panel/DatasetPanel.d.ts +11 -0
  11. package/dist/types/components/panel/PaneHeader.d.ts +1 -0
  12. package/dist/types/components/panel/PropertiesPanel.d.ts +3 -1
  13. package/dist/types/components/plugins/@antd/item-props/EchartsProps.d.ts +2 -2
  14. package/dist/types/components/plugins/@antd/item-props/TextProps.d.ts +1 -0
  15. package/dist/types/components/plugins/@antd/items/TableRender.d.ts +1 -0
  16. package/dist/types/components/plugins/@antd/items/TextRender.d.ts +1 -0
  17. package/dist/types/components/typing.d.ts +97 -2
  18. package/dist/types/components/utils.d.ts +1 -0
  19. package/dist/umd/css/bi-sdk.css +1 -1
  20. package/dist/umd/js/bi-sdk.umd.min.js +274 -67
  21. package/package.json +1 -1
  22. package/src/components/PageDesigner.tsx +229 -36
  23. package/src/components/context/DesignerContext.tsx +15 -3
  24. package/src/components/context/EnvContext.tsx +4 -1
  25. package/src/components/icon/IconFont.tsx +15 -11
  26. package/src/components/layout/PageCanvas.tsx +4 -2
  27. package/src/components/layout/PageItem.tsx +1 -1
  28. package/src/components/panel/AiPanel.tsx +609 -43
  29. package/src/components/panel/ChatInput.tsx +259 -147
  30. package/src/components/panel/DatasetPanel.tsx +65 -0
  31. package/src/components/panel/PaneHeader.tsx +3 -2
  32. package/src/components/panel/PropertiesPanel.tsx +332 -125
  33. package/src/components/plugins/@antd/index.ts +12 -8
  34. package/src/components/plugins/@antd/item-props/EchartsProps.tsx +52 -22
  35. package/src/components/plugins/@antd/item-props/HtmlProps.tsx +8 -9
  36. package/src/components/plugins/@antd/item-props/TextProps.tsx +13 -1
  37. package/src/components/plugins/@antd/items/EchartsRender.tsx +9 -1
  38. package/src/components/plugins/@antd/items/HtmlRender.tsx +13 -1
  39. package/src/components/plugins/@antd/items/ListRender.tsx +18 -1
  40. package/src/components/plugins/@antd/items/TableRender.tsx +16 -1
  41. package/src/components/plugins/@antd/items/TextRender.tsx +3 -1
  42. package/src/components/styles.css +20 -0
  43. package/src/components/typing.ts +111 -2
  44. package/src/components/utils.ts +40 -0
  45. package/src/example.tsx +314 -13
@@ -2,6 +2,7 @@ import React, { useRef } from "react";
2
2
  import { Form } from "antd";
3
3
  import Editor from "@monaco-editor/react";
4
4
  import type { PropEditorProps } from "./types";
5
+ import { IconFont } from "../../../icon/IconFont";
5
6
 
6
7
  export type HtmlModel = { template: string };
7
8
 
@@ -21,16 +22,14 @@ export const HtmlProps: React.FC<PropEditorProps<HtmlModel>> = ({
21
22
  <Form layout="vertical">
22
23
  <Form.Item
23
24
  label={
24
- <div
25
- style={{
26
- display: "flex",
27
- alignItems: "center",
28
- justifyContent: "space-between",
29
- }}
30
- >
31
- 模板 <a onClick={format}>格式化</a>
32
- </div>
25
+ <>
26
+ 模板
27
+ <a onClick={format}>
28
+ <IconFont type="icon-formate" /> 格式化
29
+ </a>
30
+ </>
33
31
  }
32
+ className="ant-form-item-label-space"
34
33
  >
35
34
  <div
36
35
  style={{
@@ -2,7 +2,11 @@ import React from "react";
2
2
  import { Form, Input, Select, Button, Space, ColorPicker } from "antd";
3
3
  import type { PropEditorProps } from "./types";
4
4
 
5
- export type TextModel = { text?: string; customStyle?: React.CSSProperties };
5
+ export type TextModel = {
6
+ text?: string;
7
+ customStyle?: React.CSSProperties;
8
+ classNames?: string[];
9
+ };
6
10
 
7
11
  export const TextProps: React.FC<PropEditorProps<TextModel>> = ({
8
12
  model,
@@ -23,6 +27,14 @@ export const TextProps: React.FC<PropEditorProps<TextModel>> = ({
23
27
  onChange={(e) => triggerModel("text", e.target.value)}
24
28
  />
25
29
  </Form.Item>
30
+ <Form.Item label="类名">
31
+ <Select
32
+ size="small"
33
+ value={model.classNames}
34
+ mode="tags"
35
+ onChange={(value) => triggerModel("classNames", value)}
36
+ />
37
+ </Form.Item>
26
38
  <div
27
39
  style={{
28
40
  display: "flex",
@@ -1,7 +1,9 @@
1
- import React, { useEffect, useRef, useState } from "react";
1
+ import React, { useContext, useEffect, useRef, useState } from "react";
2
2
  import * as echarts from "echarts";
3
3
  import { HtmlBaseProps } from "../../../typing";
4
4
  import { useDatasource } from "../../../hooks/datasource";
5
+ import { EnvContext } from "../../../context/EnvContext";
6
+ import { getVars } from "../../../utils";
5
7
 
6
8
  export type EchartsRenderProps = {
7
9
  item: any;
@@ -19,6 +21,7 @@ export const EchartsRender: React.FC<EchartsRenderProps> = ({
19
21
  style,
20
22
  className,
21
23
  }) => {
24
+ const { initCallback, env } = useContext(EnvContext);
22
25
  const chartRef = useRef<HTMLDivElement | null>(null);
23
26
  const [chart, setChart] = useState<echarts.ECharts | null>(null);
24
27
  const datasource = useDatasource(id, item.datasource);
@@ -68,12 +71,17 @@ export const EchartsRender: React.FC<EchartsRenderProps> = ({
68
71
  }
69
72
  }
70
73
  };
74
+ const callback = () => {
75
+ const vars = getVars(env, item);
76
+ console.log("callback echarts", vars);
77
+ };
71
78
  useEffect(() => {
72
79
  if (!chartRef.current) return;
73
80
  const next = echarts.init(chartRef.current);
74
81
  setChart(next);
75
82
  const onResize = () => next.resize();
76
83
  window.addEventListener("resize", onResize);
84
+ initCallback({ id: item.id, callback });
77
85
  return () => {
78
86
  window.removeEventListener("resize", onResize);
79
87
  next.dispose();
@@ -1,6 +1,8 @@
1
- import React, { useMemo } from "react";
1
+ import React, { useContext, useEffect, useMemo } from "react";
2
2
  import { HtmlBaseProps } from "../../../typing";
3
3
  import { useDatasource } from "../../../hooks/datasource";
4
+ import { getVars } from "../../../utils";
5
+ import { EnvContext } from "../../../context/EnvContext";
4
6
 
5
7
  export type HtmlRenderProps = {
6
8
  dataSource?: Record<string, any>;
@@ -27,6 +29,7 @@ export const HtmlRender: React.FC<HtmlRenderProps> = ({
27
29
  style,
28
30
  className,
29
31
  }) => {
32
+ const { env, initCallback } = useContext(EnvContext);
30
33
  const datasource = useDatasource(id, item.datasource);
31
34
  const keys = useMemo(() => Object.keys(datasource || {}), [datasource]);
32
35
  const func = (path: string) =>
@@ -63,6 +66,15 @@ export const HtmlRender: React.FC<HtmlRenderProps> = ({
63
66
  [template, args]
64
67
  );
65
68
 
69
+ const callback = () => {
70
+ const vars = getVars(env, item);
71
+ console.log("callback html", vars);
72
+ };
73
+
74
+ useEffect(() => {
75
+ initCallback({ id: item.id, callback });
76
+ }, []);
77
+
66
78
  return (
67
79
  <div
68
80
  id={id}
@@ -1,8 +1,15 @@
1
- import React, { MouseEventHandler, useMemo } from "react";
1
+ import React, {
2
+ MouseEventHandler,
3
+ useContext,
4
+ useEffect,
5
+ useMemo,
6
+ } from "react";
2
7
  import { Avatar, Pagination } from "antd";
3
8
  import styled, { css } from "styled-components";
4
9
  import { HtmlBaseProps } from "../../../typing";
5
10
  import { useDatasource } from "../../../hooks/datasource";
11
+ import { getVars } from "../../../utils";
12
+ import { EnvContext } from "../../../context/EnvContext";
6
13
 
7
14
  type DataItem = {
8
15
  title?: string;
@@ -184,6 +191,7 @@ export const ListRender: React.FC<ListRenderProps> = ({
184
191
  style = {},
185
192
  className,
186
193
  }) => {
194
+ const { env, initCallback } = useContext(EnvContext);
187
195
  const datasource = useDatasource(id, item.datasource);
188
196
  const list = datasource || [];
189
197
  const pagination = useMemo(() => {
@@ -208,6 +216,15 @@ export const ListRender: React.FC<ListRenderProps> = ({
208
216
  bordered ? "p-list--bordered" : undefined,
209
217
  className,
210
218
  ];
219
+
220
+ const callback = () => {
221
+ const vars = getVars(env, item);
222
+ console.log("callback list", vars);
223
+ };
224
+
225
+ useEffect(() => {
226
+ initCallback({ id: item.id, callback });
227
+ }, []);
211
228
  return (
212
229
  <div
213
230
  id={id}
@@ -1,6 +1,8 @@
1
- import React from "react";
1
+ import React, { useContext, useEffect } from "react";
2
2
  import { Table, type TableProps } from "antd";
3
3
  import { HtmlBaseProps } from "../../../typing";
4
+ import { getVars } from "../../../utils";
5
+ import { EnvContext } from "../../../context/EnvContext";
4
6
 
5
7
  export type TableRenderProps = {
6
8
  dataSource?: any[];
@@ -9,10 +11,12 @@ export type TableRenderProps = {
9
11
  bordered?: boolean;
10
12
  size?: TableProps["size"];
11
13
  showHeader?: boolean;
14
+ item: any;
12
15
  } & HtmlBaseProps;
13
16
 
14
17
  export const TableRender: React.FC<TableRenderProps> = ({
15
18
  id,
19
+ item,
16
20
  dataSource = [],
17
21
  columns = [],
18
22
  pageSize = 10,
@@ -22,6 +26,7 @@ export const TableRender: React.FC<TableRenderProps> = ({
22
26
  style = {},
23
27
  className,
24
28
  }) => {
29
+ const { env, initCallback } = useContext(EnvContext);
25
30
  const pagination =
26
31
  !pageSize || pageSize <= dataSource.length
27
32
  ? false
@@ -82,6 +87,16 @@ export const TableRender: React.FC<TableRenderProps> = ({
82
87
  );
83
88
  },
84
89
  }));
90
+
91
+ const callback = () => {
92
+ const vars = getVars(env, item);
93
+ console.log("callback table", vars);
94
+ };
95
+
96
+ useEffect(() => {
97
+ initCallback({ id: item.id, callback });
98
+ }, []);
99
+
85
100
  return (
86
101
  <Table
87
102
  id={id}
@@ -5,6 +5,7 @@ export type TextRenderProps = {
5
5
  text?: string;
6
6
  customStyle?: React.CSSProperties;
7
7
  item?: { style?: React.CSSProperties };
8
+ classNames?: string[];
8
9
  } & HtmlBaseProps;
9
10
 
10
11
  export const TextRender: React.FC<TextRenderProps> = ({
@@ -14,6 +15,7 @@ export const TextRender: React.FC<TextRenderProps> = ({
14
15
  style = {},
15
16
  customStyle = {},
16
17
  className,
18
+ classNames = [],
17
19
  }) => {
18
20
  const actualStyle = useMemo(
19
21
  () => ({
@@ -24,7 +26,7 @@ export const TextRender: React.FC<TextRenderProps> = ({
24
26
  [item, customStyle, style]
25
27
  );
26
28
  return (
27
- <span id={id} style={actualStyle} className={className}>
29
+ <span id={id} style={actualStyle} className={(classNames || []).join(" ") + (" " + className || "")}>
28
30
  {text}
29
31
  </span>
30
32
  );
@@ -10,3 +10,23 @@ a.toolbar {
10
10
  color: var(--ant-color-primary);
11
11
  }
12
12
  }
13
+
14
+ .ant-form-compact .ant-form-item {
15
+ margin-bottom: 8px;
16
+ }
17
+
18
+ .ant-form-item-label label {
19
+ display: inline-flex;
20
+ align-items: center;
21
+ }
22
+
23
+ .ant-form-item.ant-form-item-label-space .ant-form-item-label label {
24
+ width: 100%;
25
+ display: flex;
26
+ align-items: center;
27
+ justify-content: space-between;
28
+
29
+ &::after {
30
+ content: none;
31
+ }
32
+ }
@@ -1,4 +1,83 @@
1
- import { MouseEventHandler } from "react";
1
+ import React, { MouseEventHandler } from "react";
2
+
3
+ export type ChatRequestType = {
4
+ message: string;
5
+ files?: { id: string; name: string; extension: string }[] | null;
6
+ agents?: { id: string | number; name: string }[] | null;
7
+ page?: PageSchema | null;
8
+ pageItems?: SchemaItemType[] | null;
9
+ };
10
+
11
+ export type ChatResponseAnswerEffectType = {
12
+ datasets?: DataSetType[] | null;
13
+ schema?: PageSchema;
14
+ pageItems?: SchemaItemType[] | null;
15
+ };
16
+
17
+ export type ChatResponseAnswerType = {
18
+ answer: string;
19
+ effect?: ChatResponseAnswerEffectType | null;
20
+ extra?:
21
+ | { id: string; element: string; action: string; area: string }[]
22
+ | null;
23
+ };
24
+
25
+ export type ChatResponseType = {
26
+ id: string;
27
+ answer: ChatResponseAnswerType;
28
+ createdAt: string;
29
+ conversation?: ChatConversationType | null;
30
+ };
31
+
32
+ export type ChatConversationType = {
33
+ id: string;
34
+ name: string;
35
+ createdAt: string;
36
+ isActived: boolean;
37
+ };
38
+
39
+ export type ChatMessageType = {
40
+ id: string;
41
+ conversationId: string | null;
42
+ question: string;
43
+ answer: ChatResponseAnswerType;
44
+ files: { id: string; name: string; extension: string }[];
45
+ agents: { id: string | number; name: string }[];
46
+ createdAt: string;
47
+ sending?: boolean;
48
+ };
49
+
50
+ export type FetchType = {
51
+ upload?: (file: File) => Promise<{ id: string; name: string }>;
52
+ ai?: {
53
+ chat: (
54
+ bizType: string,
55
+ bizId: string,
56
+ conversationId: string | null,
57
+ request: ChatRequestType
58
+ ) => Promise<ChatResponseType>;
59
+ conversationList: (
60
+ bizType: string,
61
+ bizId: string
62
+ ) => Promise<ChatConversationType[]>;
63
+ messageList: (
64
+ bizType: string,
65
+ bizId: string,
66
+ conversationId?: string | null
67
+ ) => Promise<ChatMessageType[]>;
68
+ removeConversation: (
69
+ bizType: string,
70
+ bizId: string,
71
+ conversationId: string
72
+ ) => Promise<boolean>;
73
+ removeMessage: (
74
+ bizType: string,
75
+ bizId: string,
76
+ messageId: string
77
+ ) => Promise<boolean>;
78
+ };
79
+ dataset?: (dataSetId: string, params: Record<string, any>) => Promise<any>;
80
+ };
2
81
 
3
82
  export type HtmlBaseProps = {
4
83
  id?: string;
@@ -17,10 +96,11 @@ export type SchemaItemType = {
17
96
  cascadeIds?: string[];
18
97
  children?: SchemaItemType[] | Record<string, SchemaItemType[]>;
19
98
  datasource?: {
20
- source?: "custom" | "define";
99
+ source?: "custom" | "define" | "dataset";
21
100
  datasourceId?: string | null;
22
101
  scriptId?: string | null;
23
102
  custom?: string | null;
103
+ dataset?: DataSetType;
24
104
  };
25
105
  };
26
106
 
@@ -58,6 +138,31 @@ export type SqlType = {
58
138
  query: string;
59
139
  };
60
140
 
141
+ export enum FieldType {
142
+ STRING = "STRING",
143
+ NUMBER = "NUMBER",
144
+ BOOLEAN = "BOOLEAN",
145
+ OBJECT = "OBJECT",
146
+ ARRAY = "ARRAY",
147
+ }
148
+
149
+ export type DataSetOutputField = {
150
+ key?: string;
151
+ name?: string;
152
+ type?: FieldType;
153
+ schema?: DataSetOutput;
154
+ };
155
+
156
+ export type DataSetOutput = {
157
+ fields?: DataSetOutputField[];
158
+ };
159
+
160
+ export type DataSetType = {
161
+ id: string;
162
+ name: string;
163
+ output: DataSetOutput;
164
+ };
165
+
61
166
  export type PageInfo = {
62
167
  name?: string;
63
168
  description?: string;
@@ -78,3 +183,7 @@ export type EnvType = {
78
183
  };
79
184
 
80
185
  export type CallbacksType = Record<string, (v: any) => void>;
186
+
187
+ export type DatasetSelectorFunction = (
188
+ onSelect: (dataset: DataSetType) => void
189
+ ) => React.ReactNode;
@@ -35,3 +35,43 @@ export const handleCallback = (
35
35
  };
36
36
 
37
37
  export const uuid = () => v4();
38
+
39
+
40
+
41
+ export const formatTime = (dateStr: string) => {
42
+ if (!dateStr) return "";
43
+ const date = new Date(dateStr);
44
+ const now = new Date();
45
+ const diff = now.getTime() - date.getTime();
46
+
47
+ if (diff < 60 * 1000) {
48
+ return "刚刚";
49
+ }
50
+ if (diff < 60 * 60 * 1000) {
51
+ return `${Math.floor(diff / (60 * 1000))}分钟前`;
52
+ }
53
+
54
+ const pad = (n: number) => n.toString().padStart(2, "0");
55
+ const HH = pad(date.getHours());
56
+ const mm = pad(date.getMinutes());
57
+
58
+ const isToday =
59
+ date.getDate() === now.getDate() &&
60
+ date.getMonth() === now.getMonth() &&
61
+ date.getFullYear() === now.getFullYear();
62
+
63
+ if (isToday) {
64
+ return `${HH}:${mm}`;
65
+ }
66
+
67
+ const MM = pad(date.getMonth() + 1);
68
+ const DD = pad(date.getDate());
69
+ const isThisYear = date.getFullYear() === now.getFullYear();
70
+
71
+ if (isThisYear) {
72
+ return `${MM}-${DD} ${HH}:${mm}`;
73
+ }
74
+
75
+ const YYYY = date.getFullYear();
76
+ return `${YYYY}-${MM}-${DD} ${HH}:${mm}`;
77
+ };