@baishuyun/chat-sdk 0.0.16 → 0.0.17
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 +8 -0
- package/dist/chat-sdk.js +16293 -15784
- package/dist/chat-sdk.js.map +1 -1
- package/dist/chat-sdk.umd.cjs +149 -149
- package/dist/chat-sdk.umd.cjs.map +1 -1
- package/dist/index.css +1 -1
- package/package.json +4 -4
- package/src/chat.tsx +15 -1
- package/src/components/biz-comp/FieldChecker.tsx +49 -7
- package/src/components/biz-comp/FieldCheckerListMsg.tsx +101 -22
- package/src/components/biz-comp/chat-client.tsx +7 -2
- package/src/components/biz-comp/error-msg.tsx +10 -0
- package/src/components/biz-comp/messages.tsx +10 -0
- package/src/components/biz-comp/multi-modal-input/clear-btn.tsx +3 -1
- package/src/components/biz-comp/multi-modal-input/index.tsx +58 -38
- package/src/components/biz-comp/multi-modal-input/prompt-input.tsx +13 -10
- package/src/components/biz-comp/preview-message-wrapper.tsx +4 -4
- package/src/components/biz-comp/preview-message.tsx +3 -1
- package/src/components/biz-comp/suggestions.tsx +5 -1
- package/src/components/bs-ui/attachments-previewer.tsx +4 -1
- package/src/components/bs-ui/base-button.tsx +7 -2
- package/src/components/bs-ui/bs-icons.tsx +29 -0
- package/src/components/bs-ui/card.tsx +4 -3
- package/src/components/bs-ui/chat-area-header.tsx +7 -3
- package/src/components/bs-ui/fields-design-info-table.tsx +160 -0
- package/src/components/bs-ui/fields-previewer.tsx +2 -0
- package/src/components/bs-ui/form-info-editor.tsx +2 -42
- package/src/components/bs-ui/generate-animation.tsx +7 -5
- package/src/components/bs-ui/img-part.tsx +1 -1
- package/src/components/bs-ui/line-checker.tsx +19 -5
- package/src/components/bs-ui/previewer-header.tsx +28 -3
- package/src/components/bs-ui/square-checker.tsx +30 -5
- package/src/components/bs-ui/tooltip.tsx +1 -1
- package/src/components/ui/dialog.tsx +1 -1
- package/src/components/ui/tooltip.tsx +1 -1
- package/src/const/ui.ts +42 -0
- package/src/hooks/use-frame-mode.ts +15 -0
- package/src/lib/parse-design-doc.ts +60 -0
- package/src/lib/utils.ts +19 -0
- package/src/plugins/form-builder-base-plugin/const.ts +3 -0
- package/src/plugins/form-builder-plugin/components/create-form-confirm.tsx +14 -1
- package/src/plugins/form-builder-plugin/components/design-info.tsx +47 -0
- package/src/plugins/form-builder-plugin/components/entry-btn.tsx +10 -2
- package/src/plugins/form-builder-plugin/components/follow-up.tsx +21 -6
- package/src/plugins/form-builder-plugin/components/msg-part.tsx +29 -9
- package/src/plugins/form-builder-plugin/components/opening-lines.tsx +11 -6
- package/src/plugins/form-builder-plugin/index.ts +73 -5
- package/src/plugins/form-builder-plugin/types.ts +3 -0
- package/src/plugins/form-builder-plugin/utils/index.ts +33 -6
- package/src/plugins/form-filling-plugin/components/batch-generator-action.tsx +44 -34
- package/src/plugins/form-filling-plugin/components/first-batch-generating-animation.tsx +21 -0
- package/src/plugins/form-filling-plugin/components/generated-data-counter.tsx +17 -0
- package/src/plugins/form-filling-plugin/components/non-first-batch-generating-animation.tsx +28 -0
- package/src/plugins/form-filling-plugin/index.ts +14 -0
- package/src/plugins/form-filling-plugin/types.ts +2 -0
- package/src/plugins/report-query-plugin/components/query-msg-part.tsx +16 -18
- package/src/plugins/report-query-plugin/components/result-cards/CreatedSourceMsg.tsx +36 -0
- package/src/plugins/report-query-plugin/components/result-cards/DataTableCard.tsx +15 -2
- package/src/plugins/report-query-plugin/const.ts +22 -0
- package/src/plugins/report-query-plugin/index.ts +30 -3
- package/src/plugins/report-query-plugin/types.ts +6 -0
- package/src/sdk.impl.tsx +4 -0
- package/src/store/index.ts +11 -0
- package/src/stories/FormInfoEditor.stories.tsx +19 -28
- package/src/stories/fields-design-info-table.stories.tsx +203 -0
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { BorderColorAnimation } from '@/components/bs-ui/border-color-animation';
|
|
2
|
-
import { GenerateAnimation } from '@/components/bs-ui/generate-animation';
|
|
3
1
|
import { PrimaryConfirmBtn } from '@/components/bs-ui/primary-confirm-btn';
|
|
4
2
|
import { TextUIPart } from 'ai';
|
|
5
3
|
import { memo, useCallback, useEffect, useRef, useState } from 'react';
|
|
@@ -11,7 +9,10 @@ import { DATA_COUNT_PER_BATCH, FILLING_EVENTS, PLUGIN_NAME } from '../const';
|
|
|
11
9
|
import { useEvtBus } from '@/hooks/use-evt-bus';
|
|
12
10
|
import { ChatMessage, UseChatHelpers } from '@baishuyun/types';
|
|
13
11
|
import { type Field } from '@/plugins/form-builder-base-plugin/types';
|
|
14
|
-
import {
|
|
12
|
+
import { GeneratedDataCounter } from './generated-data-counter';
|
|
13
|
+
import { FirstBatchGeneratingAnimation } from './first-batch-generating-animation';
|
|
14
|
+
import { NonFirstBatchGeneratingAnimation } from './non-first-batch-generating-animation';
|
|
15
|
+
import { usePlugin } from '@/hooks/use-plugin';
|
|
15
16
|
|
|
16
17
|
type FilledField = {
|
|
17
18
|
fieldName: string;
|
|
@@ -93,30 +94,51 @@ const BaseBatchGeneratorAction = ({
|
|
|
93
94
|
id,
|
|
94
95
|
fields,
|
|
95
96
|
}: BatchGeneratorActionProps) => {
|
|
97
|
+
const pluginInst = usePlugin<FormFillingPlugin>(PLUGIN_NAME);
|
|
98
|
+
|
|
96
99
|
const [streamingState, setStreamingState] = useState(status === 'streaming');
|
|
97
100
|
|
|
101
|
+
const [totalCount, setTotalCount] = useState(pluginInst?.getCount(id) || 0);
|
|
102
|
+
|
|
103
|
+
const [next, setNext] = useState(totalCount > 0);
|
|
104
|
+
|
|
98
105
|
const evtBus = useEvtBus();
|
|
99
106
|
|
|
107
|
+
const getRowNum = useCallback(() => {
|
|
108
|
+
if (!fields || fields.length === 0) {
|
|
109
|
+
return 0;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const lastField = fields[fields.length - 1];
|
|
113
|
+
return lastField.row || 0;
|
|
114
|
+
}, [fields]);
|
|
115
|
+
|
|
100
116
|
useEffect(() => {
|
|
101
117
|
if (status === 'ready' || status === 'error') {
|
|
102
118
|
setStreamingState(false);
|
|
103
119
|
}
|
|
104
120
|
}, [status]);
|
|
105
121
|
|
|
122
|
+
useEffect(() => {
|
|
123
|
+
if (!pluginInst) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (streamingState) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const newRows = getRowNum();
|
|
132
|
+
pluginInst.setCount(id, newRows);
|
|
133
|
+
|
|
134
|
+
setTotalCount(pluginInst.getCount(id) || 0);
|
|
135
|
+
}, [streamingState, getRowNum, pluginInst, id]);
|
|
136
|
+
|
|
106
137
|
const formFillingCtx: FormFillingPluginCtx | null = usePluginCtx<
|
|
107
138
|
FormFillingPluginCtx,
|
|
108
139
|
FormFillingPlugin
|
|
109
140
|
>(PLUGIN_NAME);
|
|
110
141
|
|
|
111
|
-
const getRowNum = () => {
|
|
112
|
-
if (!fields || fields.length === 0) {
|
|
113
|
-
return 0;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
const lastField = fields[fields.length - 1];
|
|
117
|
-
return lastField.row || 0;
|
|
118
|
-
};
|
|
119
|
-
|
|
120
142
|
const handleCheckChange = useCallback(
|
|
121
143
|
(checked: boolean) => {
|
|
122
144
|
evtBus.emit('form-filling-fields-checked-update', {
|
|
@@ -132,11 +154,7 @@ const BaseBatchGeneratorAction = ({
|
|
|
132
154
|
if (!streamingState) {
|
|
133
155
|
return (
|
|
134
156
|
<div className="rounded-[10px] border border-[var(--e0e0e0,#E0E0E0)] w-full flex items-center flex-col gap-[10px] p-[4px] pb-[20px]">
|
|
135
|
-
<
|
|
136
|
-
<CircleChecker defaultChecked onCheckedChange={handleCheckChange}>
|
|
137
|
-
已生成{getRowNum()}条数据
|
|
138
|
-
</CircleChecker>
|
|
139
|
-
</div>
|
|
157
|
+
<GeneratedDataCounter count={totalCount} handleCheckChange={handleCheckChange} />
|
|
140
158
|
|
|
141
159
|
<PrimaryConfirmBtn
|
|
142
160
|
text={`继续生成${DATA_COUNT_PER_BATCH}条`}
|
|
@@ -146,6 +164,8 @@ const BaseBatchGeneratorAction = ({
|
|
|
146
164
|
return;
|
|
147
165
|
}
|
|
148
166
|
|
|
167
|
+
setNext(true);
|
|
168
|
+
|
|
149
169
|
setStreamingState(true);
|
|
150
170
|
|
|
151
171
|
const formStructure = Array.from(formFillingCtx?.fieldMap.values() || []);
|
|
@@ -169,22 +189,12 @@ const BaseBatchGeneratorAction = ({
|
|
|
169
189
|
);
|
|
170
190
|
}
|
|
171
191
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
bgInset={1000}
|
|
179
|
-
borderWidth={1.5}
|
|
180
|
-
style={{
|
|
181
|
-
display: 'flex',
|
|
182
|
-
alignItems: 'center',
|
|
183
|
-
}}
|
|
184
|
-
>
|
|
185
|
-
<GenerateAnimation>数据生成中,可点击下方按钮暂停</GenerateAnimation>
|
|
186
|
-
</BorderColorAnimation>
|
|
187
|
-
);
|
|
192
|
+
const isFirstBatch = totalCount <= DATA_COUNT_PER_BATCH && !next;
|
|
193
|
+
if (isFirstBatch) {
|
|
194
|
+
return <FirstBatchGeneratingAnimation />;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return <NonFirstBatchGeneratingAnimation />;
|
|
188
198
|
};
|
|
189
199
|
|
|
190
200
|
const PartParser = ({ parts, ...rest }: BatchGeneratorActionProps) => {
|
|
@@ -218,7 +228,7 @@ export const BatchGeneratorAction = memo(PartParser, (prevProps, nextProps) => {
|
|
|
218
228
|
prevProps.parts?.length === nextProps.parts?.length &&
|
|
219
229
|
prevLastPart?.text === lastPart?.text &&
|
|
220
230
|
prevProps.status === nextProps.status &&
|
|
221
|
-
prevProps.sendMessage === nextProps.sendMessage &&
|
|
231
|
+
// prevProps.sendMessage === nextProps.sendMessage &&
|
|
222
232
|
prevProps.id === nextProps.id
|
|
223
233
|
);
|
|
224
234
|
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { BorderColorAnimation } from '@/components/bs-ui/border-color-animation';
|
|
2
|
+
import { GenerateAnimation } from '@/components/bs-ui/generate-animation';
|
|
3
|
+
|
|
4
|
+
export const FirstBatchGeneratingAnimation = () => {
|
|
5
|
+
return (
|
|
6
|
+
<BorderColorAnimation
|
|
7
|
+
width="100%"
|
|
8
|
+
height={40}
|
|
9
|
+
padding={10}
|
|
10
|
+
borderRadius={10}
|
|
11
|
+
bgInset={1000}
|
|
12
|
+
borderWidth={1.5}
|
|
13
|
+
style={{
|
|
14
|
+
display: 'flex',
|
|
15
|
+
alignItems: 'center',
|
|
16
|
+
}}
|
|
17
|
+
>
|
|
18
|
+
<GenerateAnimation>数据生成中,可点击下方按钮暂停</GenerateAnimation>
|
|
19
|
+
</BorderColorAnimation>
|
|
20
|
+
);
|
|
21
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { CircleChecker } from '@/components/bs-ui/circle-checker';
|
|
2
|
+
|
|
3
|
+
export const GeneratedDataCounter = ({
|
|
4
|
+
count,
|
|
5
|
+
handleCheckChange,
|
|
6
|
+
}: {
|
|
7
|
+
count: number;
|
|
8
|
+
handleCheckChange: (checked: boolean) => void;
|
|
9
|
+
}) => {
|
|
10
|
+
return (
|
|
11
|
+
<div className="flex items-center w-full py-[10px] px-[16px] gap-[6px]">
|
|
12
|
+
<CircleChecker defaultChecked onCheckedChange={handleCheckChange}>
|
|
13
|
+
已生成{count}条数据
|
|
14
|
+
</CircleChecker>
|
|
15
|
+
</div>
|
|
16
|
+
);
|
|
17
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { BorderColorAnimation } from '@/components/bs-ui/border-color-animation';
|
|
2
|
+
import { GenerateAnimation } from '@/components/bs-ui/generate-animation';
|
|
3
|
+
import { PrimaryConfirmBtn } from '@/components/bs-ui/primary-confirm-btn';
|
|
4
|
+
import { DATA_COUNT_PER_BATCH } from '../const';
|
|
5
|
+
|
|
6
|
+
export const NonFirstBatchGeneratingAnimation = () => {
|
|
7
|
+
return (
|
|
8
|
+
<BorderColorAnimation
|
|
9
|
+
width="100%"
|
|
10
|
+
height={110}
|
|
11
|
+
padding={4}
|
|
12
|
+
borderRadius={10}
|
|
13
|
+
bgInset={1000}
|
|
14
|
+
borderWidth={1.5}
|
|
15
|
+
style={{
|
|
16
|
+
display: 'flex',
|
|
17
|
+
alignItems: 'center',
|
|
18
|
+
}}
|
|
19
|
+
>
|
|
20
|
+
<div className="flex flex-col gap-[10px] w-full">
|
|
21
|
+
<GenerateAnimation className='ml-[16px]'>继续生成中,可点击下方暂停按钮暂停</GenerateAnimation>
|
|
22
|
+
<PrimaryConfirmBtn
|
|
23
|
+
className="w-[300px] mx-auto"
|
|
24
|
+
text={`继续生成${DATA_COUNT_PER_BATCH}条`} disabled />
|
|
25
|
+
</div>
|
|
26
|
+
</BorderColorAnimation>
|
|
27
|
+
);
|
|
28
|
+
};
|
|
@@ -91,6 +91,7 @@ export class FormFillingPlugin extends ChatAreaPlugin<FormFillingPluginCtx> {
|
|
|
91
91
|
}) => {
|
|
92
92
|
if (!visible) {
|
|
93
93
|
this.lifecycleHooks?.onBeforeMessagesClear?.();
|
|
94
|
+
this.Context.counterMap.clear();
|
|
94
95
|
}
|
|
95
96
|
};
|
|
96
97
|
|
|
@@ -102,6 +103,18 @@ export class FormFillingPlugin extends ChatAreaPlugin<FormFillingPluginCtx> {
|
|
|
102
103
|
this.Context!.fillMode = mode;
|
|
103
104
|
};
|
|
104
105
|
|
|
106
|
+
public getCount = (messageId: string): number => {
|
|
107
|
+
console.log('get count', messageId, this.Context.counterMap.get(messageId));
|
|
108
|
+
return this.Context.counterMap.get(messageId) || 0;
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
public setCount = (messageId: string, inc: number) => {
|
|
112
|
+
const existingCount = this.Context.counterMap.get(messageId) || 0;
|
|
113
|
+
const newCount = existingCount + inc;
|
|
114
|
+
console.log('set count', messageId, newCount);
|
|
115
|
+
this.Context.counterMap.set(messageId, newCount);
|
|
116
|
+
};
|
|
117
|
+
|
|
105
118
|
public dispose?: (() => void) | undefined = () => {
|
|
106
119
|
this.batchFillingDataManager.dispose();
|
|
107
120
|
|
|
@@ -229,6 +242,7 @@ export const FormFillingPluginRegisterEntry: PluginRegistryEntry<FormFillingPlug
|
|
|
229
242
|
subFieldsNameMap: new Map(),
|
|
230
243
|
conversationId: '',
|
|
231
244
|
fillMode: 'AI',
|
|
245
|
+
counterMap: new Map(),
|
|
232
246
|
};
|
|
233
247
|
},
|
|
234
248
|
};
|
|
@@ -7,10 +7,7 @@ import { usePluginCtx } from '@/hooks/use-plugin-ctx';
|
|
|
7
7
|
import { ReportQueryPlugin } from '@/index';
|
|
8
8
|
import { PLUGIN_NAME } from '../const';
|
|
9
9
|
import { IReportQueryContext } from '../types';
|
|
10
|
-
import {
|
|
11
|
-
import { HighlightMsg } from '@/components/biz-comp/highlight-msg';
|
|
12
|
-
import { CollapsibleTxtMsg } from '@/components/bs-ui/collapsible-txt-msg';
|
|
13
|
-
import { AggregateTableIcon } from '@/components/bs-ui/bs-icons';
|
|
10
|
+
import { CreatedSourceMsg } from './result-cards/CreatedSourceMsg';
|
|
14
11
|
|
|
15
12
|
export const QueryMsgPart = ({ part, ...rest }: MsgPartCompProps) => {
|
|
16
13
|
const textPart = part as TextUIPart;
|
|
@@ -29,25 +26,26 @@ export const QueryMsgPart = ({ part, ...rest }: MsgPartCompProps) => {
|
|
|
29
26
|
|
|
30
27
|
if (result.isAggregate) {
|
|
31
28
|
return (
|
|
32
|
-
<
|
|
33
|
-
<HighlightMsg>已为你创建聚合表</HighlightMsg>
|
|
34
|
-
<CollapsibleTxtMsg
|
|
35
|
-
icon={
|
|
36
|
-
<span className="text-[#0265ff]">
|
|
37
|
-
<AggregateTableIcon />
|
|
38
|
-
</span>
|
|
39
|
-
}
|
|
40
|
-
title={result.title!}
|
|
41
|
-
disableExpand
|
|
42
|
-
/>
|
|
43
|
-
</FakeBotMessage>
|
|
29
|
+
<CreatedSourceMsg type={'aggregate'} title={result.title || ''} done={textPart.state === 'done'} />
|
|
44
30
|
);
|
|
45
31
|
}
|
|
46
32
|
|
|
47
|
-
console.log('
|
|
33
|
+
console.log('queryResult', result)
|
|
34
|
+
|
|
48
35
|
ctx.queryResult = result;
|
|
49
36
|
ctx.queryResult.appID = ctx.appInfo?.appId || '';
|
|
50
|
-
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<>
|
|
40
|
+
{(result.source && (result.source !== 'aggregate')) ? (
|
|
41
|
+
<CreatedSourceMsg type={result.source} title={result.title || ''} done={textPart.state === 'done'} />
|
|
42
|
+
) : null}
|
|
43
|
+
<DataTableCard
|
|
44
|
+
{...(result || {})}
|
|
45
|
+
streaming={textPart?.state === 'streaming'}
|
|
46
|
+
></DataTableCard>
|
|
47
|
+
</>
|
|
48
|
+
);
|
|
51
49
|
}
|
|
52
50
|
|
|
53
51
|
if (textPart.text !== undefined && textPart.text.trim() !== '') {
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { FakeBotMessage } from '@/components/biz-comp/FakeBotMsg';
|
|
2
|
+
import { HighlightMsg } from '@/components/biz-comp/highlight-msg';
|
|
3
|
+
import { CollapsibleTxtMsg } from '@/components/bs-ui/collapsible-txt-msg';
|
|
4
|
+
import { QuerySourceType } from '@baishuyun/types';
|
|
5
|
+
import { CreatedSourceConfigMap } from '../../const';
|
|
6
|
+
import { useEffect } from 'react';
|
|
7
|
+
import { useFakeGlobalLoadingMessage } from '@/hooks/use-frame-mode';
|
|
8
|
+
|
|
9
|
+
export const CreatedSourceMsg = ({ type, title, done }: { type: QuerySourceType; title: string; done?: boolean }) => {
|
|
10
|
+
const config = CreatedSourceConfigMap[type];
|
|
11
|
+
if (!config) {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const loading = useFakeGlobalLoadingMessage();
|
|
16
|
+
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
// if (done) {
|
|
19
|
+
|
|
20
|
+
// }
|
|
21
|
+
loading?.clearGlobalFakeLoadingMessage();
|
|
22
|
+
|
|
23
|
+
}, [])
|
|
24
|
+
|
|
25
|
+
const icon = <config.iconComponent />;
|
|
26
|
+
return (
|
|
27
|
+
<FakeBotMessage headless className="w-full">
|
|
28
|
+
<HighlightMsg>已为你创建{config.label}</HighlightMsg>
|
|
29
|
+
<CollapsibleTxtMsg
|
|
30
|
+
icon={<span className={`text-[${config.color}]`}>{icon}</span>}
|
|
31
|
+
title={title}
|
|
32
|
+
disableExpand
|
|
33
|
+
/>
|
|
34
|
+
</FakeBotMessage>
|
|
35
|
+
);
|
|
36
|
+
};
|
|
@@ -4,16 +4,23 @@ import { IQueryResult } from '@baishuyun/types';
|
|
|
4
4
|
import { IReportQueryContext } from '../../types';
|
|
5
5
|
import { ReportQueryPlugin } from '../..';
|
|
6
6
|
import { PLUGIN_NAME } from '../../const';
|
|
7
|
-
import { useCallback } from 'react';
|
|
7
|
+
import { useCallback, useEffect } from 'react';
|
|
8
8
|
import { ConditionField, DataSourceField, DimensionField, MetricField } from './DataTableFields';
|
|
9
9
|
import { CardFieldsWrapper } from '@/components/bs-ui/card-field';
|
|
10
10
|
import { FilterCondition } from './FilterCondition';
|
|
11
11
|
import { SplitLine } from '@/components/bs-ui/split-line';
|
|
12
12
|
import { DashWidgetIcon } from '@/components/biz-comp/dash-widget-icon';
|
|
13
|
+
import { useFakeGlobalLoadingMessage } from '@/hooks/use-frame-mode';
|
|
13
14
|
|
|
14
|
-
export const DataTableCard = (
|
|
15
|
+
export const DataTableCard = (
|
|
16
|
+
props: IQueryResult & {
|
|
17
|
+
streaming?: boolean;
|
|
18
|
+
}
|
|
19
|
+
) => {
|
|
15
20
|
const ctx = usePluginCtx<IReportQueryContext, ReportQueryPlugin>(PLUGIN_NAME);
|
|
16
21
|
|
|
22
|
+
const globalLoading = useFakeGlobalLoadingMessage();
|
|
23
|
+
|
|
17
24
|
const getFormName = useCallback(
|
|
18
25
|
(id: string) => {
|
|
19
26
|
const form = ctx?.appInfo?.formMap?.get(id);
|
|
@@ -22,6 +29,12 @@ export const DataTableCard = (props: IQueryResult) => {
|
|
|
22
29
|
[ctx]
|
|
23
30
|
);
|
|
24
31
|
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
if (props.streaming) {
|
|
34
|
+
globalLoading.clearGlobalFakeLoadingMessage();
|
|
35
|
+
}
|
|
36
|
+
}, [props.streaming]);
|
|
37
|
+
|
|
25
38
|
const formId = props.formIds?.[0] || '';
|
|
26
39
|
const name = formId ? getFormName(formId) : '';
|
|
27
40
|
|
|
@@ -1 +1,23 @@
|
|
|
1
|
+
import { QuerySourceType } from '@baishuyun/types';
|
|
2
|
+
import { ICreatedSourceConfig } from './types';
|
|
3
|
+
import { AggregateTableIcon, DataReportIcon, DataViewIcon } from '@/components/bs-ui/bs-icons';
|
|
4
|
+
|
|
1
5
|
export const PLUGIN_NAME = 'ReportQueryPlugin';
|
|
6
|
+
|
|
7
|
+
export const CreatedSourceConfigMap: Record<QuerySourceType, ICreatedSourceConfig> = {
|
|
8
|
+
etl: {
|
|
9
|
+
label: '数据视图',
|
|
10
|
+
color: '#0265ff',
|
|
11
|
+
iconComponent: DataViewIcon,
|
|
12
|
+
},
|
|
13
|
+
aggregate: {
|
|
14
|
+
label: '聚合表',
|
|
15
|
+
color: '#0265ff',
|
|
16
|
+
iconComponent: AggregateTableIcon,
|
|
17
|
+
},
|
|
18
|
+
report: {
|
|
19
|
+
label: '数据报表',
|
|
20
|
+
color: '#4ACC8C',
|
|
21
|
+
iconComponent: DataReportIcon,
|
|
22
|
+
},
|
|
23
|
+
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ChatAreaPlugin,
|
|
3
|
+
IChatSDK,
|
|
3
4
|
IDashForm,
|
|
4
5
|
PluginCustomComponent,
|
|
5
6
|
PluginHooks,
|
|
@@ -14,6 +15,12 @@ import { QueryMsgPart } from './components/query-msg-part';
|
|
|
14
15
|
import { queryResult2createParams, queryResult2previewerProps } from './utils';
|
|
15
16
|
|
|
16
17
|
export class ReportQueryPlugin extends ChatAreaPlugin<IReportQueryContext> {
|
|
18
|
+
private _inst: IChatSDK | null = null;
|
|
19
|
+
|
|
20
|
+
public init?: ((sdk: IChatSDK) => void) | undefined = (sdkInst: IChatSDK) => {
|
|
21
|
+
this._inst = sdkInst;
|
|
22
|
+
};
|
|
23
|
+
|
|
17
24
|
public pluginName: string = PLUGIN_NAME;
|
|
18
25
|
|
|
19
26
|
public customComponents?: Partial<PluginCustomComponent> | undefined = {
|
|
@@ -24,8 +31,20 @@ export class ReportQueryPlugin extends ChatAreaPlugin<IReportQueryContext> {
|
|
|
24
31
|
};
|
|
25
32
|
|
|
26
33
|
public lifecycleHooks?: PluginHooks | undefined = {
|
|
34
|
+
onBeforeMessagesClear: (conversationId) => {
|
|
35
|
+
const req = async () => {
|
|
36
|
+
await fetch(`https://agent.online-office.net/web/api/form/conversation/clear`, {
|
|
37
|
+
// await fetch(`http://192.168.50.38:3001/web/api/form/conversation/clear`, {
|
|
38
|
+
method: 'POST',
|
|
39
|
+
body: JSON.stringify({ conversationId }),
|
|
40
|
+
});
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
req();
|
|
44
|
+
},
|
|
45
|
+
|
|
27
46
|
onAfterChatAreaHide: ({ clearMsgs }) => {
|
|
28
|
-
|
|
47
|
+
clearMsgs();
|
|
29
48
|
},
|
|
30
49
|
|
|
31
50
|
onBeforeChatRender: () => {
|
|
@@ -43,6 +62,11 @@ export class ReportQueryPlugin extends ChatAreaPlugin<IReportQueryContext> {
|
|
|
43
62
|
},
|
|
44
63
|
};
|
|
45
64
|
},
|
|
65
|
+
|
|
66
|
+
onAfterMessageSend: (_) => {
|
|
67
|
+
console.log('enter onAfterMessageSend hook in ReportQueryPlugin');
|
|
68
|
+
this.setLoadingMsg('正在处理');
|
|
69
|
+
},
|
|
46
70
|
};
|
|
47
71
|
|
|
48
72
|
public getPreviewerProps = (entryId: string) => {
|
|
@@ -92,14 +116,17 @@ export class ReportQueryPlugin extends ChatAreaPlugin<IReportQueryContext> {
|
|
|
92
116
|
console.log('forms received in plugin:', formMap);
|
|
93
117
|
};
|
|
94
118
|
|
|
119
|
+
private setLoadingMsg = (message: string) => {
|
|
120
|
+
this._inst?.setGlobalLoadingMessage(message);
|
|
121
|
+
};
|
|
122
|
+
|
|
95
123
|
public constructor(ctx: IReportQueryContext) {
|
|
96
124
|
super(ctx);
|
|
97
125
|
this.Context = ctx;
|
|
98
126
|
}
|
|
99
127
|
|
|
100
128
|
public clearCtx = () => {
|
|
101
|
-
|
|
102
|
-
// this.Context.queryResult = undefined;
|
|
129
|
+
this.Context.queryResult = undefined;
|
|
103
130
|
};
|
|
104
131
|
}
|
|
105
132
|
|
package/src/sdk.impl.tsx
CHANGED
|
@@ -69,6 +69,10 @@ export class ChatSDK implements IChatSDK {
|
|
|
69
69
|
this.Store.getState().setChatAreaPluginInstList(instList);
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
+
public setGlobalLoadingMessage(message?: string): void {
|
|
73
|
+
this.Store.getState().setGlobalFakeLoadingMessage(message);
|
|
74
|
+
}
|
|
75
|
+
|
|
72
76
|
public getPluginCtx<T>(pluginName: string): DeepReadonly<T> | undefined {
|
|
73
77
|
const pluginInst = this.Store.getState().chatAreaPluginInstList.find(
|
|
74
78
|
(inst) => inst.pluginName === pluginName
|
package/src/store/index.ts
CHANGED
|
@@ -23,6 +23,7 @@ export const createStore = (sdkInst: ChatSDK) => {
|
|
|
23
23
|
clientStyle: '',
|
|
24
24
|
|
|
25
25
|
msgClearTimestamp: Date.now(),
|
|
26
|
+
globalFakeLoadingMessage: '',
|
|
26
27
|
};
|
|
27
28
|
|
|
28
29
|
return create<ChatContextType>()(
|
|
@@ -36,6 +37,16 @@ export const createStore = (sdkInst: ChatSDK) => {
|
|
|
36
37
|
|
|
37
38
|
clearMessages: () => set(() => ({ msgClearTimestamp: Date.now() })),
|
|
38
39
|
|
|
40
|
+
clearGlobalFakeLoadingMessage: () =>
|
|
41
|
+
set(() => ({
|
|
42
|
+
globalFakeLoadingMessage: undefined,
|
|
43
|
+
})),
|
|
44
|
+
|
|
45
|
+
setGlobalFakeLoadingMessage: (message) =>
|
|
46
|
+
set(() => ({
|
|
47
|
+
globalFakeLoadingMessage: message,
|
|
48
|
+
})),
|
|
49
|
+
|
|
39
50
|
setChatStatus: (status: ChatStatus) =>
|
|
40
51
|
set(() => ({
|
|
41
52
|
chatStatus: status,
|
|
@@ -1,21 +1,18 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from
|
|
2
|
-
import { useState } from
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { useState } from 'react';
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
FormIconOption,
|
|
7
|
-
FORM_ICON_OPTIONS,
|
|
8
|
-
} from "@/components/bs-ui/form-info-editor";
|
|
4
|
+
import { FormInfoEditor, FormIconOption } from '@/components/bs-ui/form-info-editor';
|
|
5
|
+
import { FORM_ICON_OPTIONS } from '@/const/ui';
|
|
9
6
|
|
|
10
7
|
const meta: Meta<typeof FormInfoEditor> = {
|
|
11
|
-
title:
|
|
8
|
+
title: 'Example/Chat/FormInfoEditor',
|
|
12
9
|
component: FormInfoEditor,
|
|
13
|
-
tags: [
|
|
10
|
+
tags: ['autodocs'],
|
|
14
11
|
parameters: {
|
|
15
|
-
layout:
|
|
12
|
+
layout: 'centered',
|
|
16
13
|
},
|
|
17
14
|
args: {
|
|
18
|
-
name:
|
|
15
|
+
name: '供应商管理表',
|
|
19
16
|
},
|
|
20
17
|
decorators: [
|
|
21
18
|
(Story) => (
|
|
@@ -32,7 +29,7 @@ type Story = StoryObj<typeof meta>;
|
|
|
32
29
|
// Default collapsed state
|
|
33
30
|
export const Default: Story = {
|
|
34
31
|
args: {
|
|
35
|
-
name:
|
|
32
|
+
name: '供应商管理表',
|
|
36
33
|
selectedIcon: FORM_ICON_OPTIONS[0],
|
|
37
34
|
},
|
|
38
35
|
};
|
|
@@ -40,7 +37,7 @@ export const Default: Story = {
|
|
|
40
37
|
// Expanded edit state
|
|
41
38
|
export const Expanded: Story = {
|
|
42
39
|
args: {
|
|
43
|
-
name:
|
|
40
|
+
name: '供应商管理表',
|
|
44
41
|
expanded: true,
|
|
45
42
|
selectedIcon: FORM_ICON_OPTIONS[0],
|
|
46
43
|
},
|
|
@@ -49,7 +46,7 @@ export const Expanded: Story = {
|
|
|
49
46
|
// With icon options in expanded state (using all 36 form icons)
|
|
50
47
|
export const WithIconOptions: Story = {
|
|
51
48
|
args: {
|
|
52
|
-
name:
|
|
49
|
+
name: '供应商管理表',
|
|
53
50
|
expanded: true,
|
|
54
51
|
iconOptions: FORM_ICON_OPTIONS,
|
|
55
52
|
selectedIcon: FORM_ICON_OPTIONS[20],
|
|
@@ -65,11 +62,9 @@ export const WithIconOptions: Story = {
|
|
|
65
62
|
|
|
66
63
|
// Interactive example with state management
|
|
67
64
|
const InteractiveTemplate = () => {
|
|
68
|
-
const [name, setName] = useState(
|
|
65
|
+
const [name, setName] = useState('供应商管理表');
|
|
69
66
|
const [expanded, setExpanded] = useState(false);
|
|
70
|
-
const [selectedIcon, setSelectedIcon] = useState<FormIconOption>(
|
|
71
|
-
FORM_ICON_OPTIONS[0]
|
|
72
|
-
);
|
|
67
|
+
const [selectedIcon, setSelectedIcon] = useState<FormIconOption>(FORM_ICON_OPTIONS[0]);
|
|
73
68
|
|
|
74
69
|
return (
|
|
75
70
|
<FormInfoEditor
|
|
@@ -101,7 +96,7 @@ export const Interactive: Story = {
|
|
|
101
96
|
// Long form name - test ellipsis
|
|
102
97
|
export const LongName: Story = {
|
|
103
98
|
args: {
|
|
104
|
-
name:
|
|
99
|
+
name: '这是一个很长的表单名称用于测试文本溢出情况显示省略号',
|
|
105
100
|
selectedIcon: FORM_ICON_OPTIONS[5],
|
|
106
101
|
},
|
|
107
102
|
};
|
|
@@ -109,8 +104,8 @@ export const LongName: Story = {
|
|
|
109
104
|
// Custom width
|
|
110
105
|
export const CustomWidth: Story = {
|
|
111
106
|
args: {
|
|
112
|
-
name:
|
|
113
|
-
className:
|
|
107
|
+
name: '供应商管理表',
|
|
108
|
+
className: 'w-[400px]',
|
|
114
109
|
selectedIcon: FORM_ICON_OPTIONS[0],
|
|
115
110
|
},
|
|
116
111
|
decorators: [
|
|
@@ -125,7 +120,7 @@ export const CustomWidth: Story = {
|
|
|
125
120
|
// Expanded with long name
|
|
126
121
|
export const ExpandedLongName: Story = {
|
|
127
122
|
args: {
|
|
128
|
-
name:
|
|
123
|
+
name: '这是一个很长的表单名称用于测试文本溢出情况',
|
|
129
124
|
expanded: true,
|
|
130
125
|
iconOptions: FORM_ICON_OPTIONS.slice(0, 18), // Show 18 icons (3 rows)
|
|
131
126
|
selectedIcon: FORM_ICON_OPTIONS[0],
|
|
@@ -135,7 +130,7 @@ export const ExpandedLongName: Story = {
|
|
|
135
130
|
// Empty name
|
|
136
131
|
export const EmptyName: Story = {
|
|
137
132
|
args: {
|
|
138
|
-
name:
|
|
133
|
+
name: '',
|
|
139
134
|
expanded: true,
|
|
140
135
|
selectedIcon: FORM_ICON_OPTIONS[0],
|
|
141
136
|
},
|
|
@@ -147,11 +142,7 @@ export const SideBySide: Story = {
|
|
|
147
142
|
<div className="flex flex-col gap-4 w-[328px]">
|
|
148
143
|
<div>
|
|
149
144
|
<p className="text-sm text-gray-500 mb-2">默认状态 (收起)</p>
|
|
150
|
-
<FormInfoEditor
|
|
151
|
-
name="供应商管理表"
|
|
152
|
-
expanded={false}
|
|
153
|
-
selectedIcon={FORM_ICON_OPTIONS[0]}
|
|
154
|
-
/>
|
|
145
|
+
<FormInfoEditor name="供应商管理表" expanded={false} selectedIcon={FORM_ICON_OPTIONS[0]} />
|
|
155
146
|
</div>
|
|
156
147
|
<div>
|
|
157
148
|
<p className="text-sm text-gray-500 mb-2">长名称 (带省略号)</p>
|