@baishuyun/chat-sdk 0.0.16 → 0.0.18
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/.turbo/turbo-build.log +178 -115
- package/CHANGELOG.md +16 -0
- package/dist/chat-sdk.js +37309 -44637
- package/dist/chat-sdk.js.map +1 -1
- package/dist/chat-sdk.umd.cjs +218 -295
- package/dist/chat-sdk.umd.cjs.map +1 -1
- package/dist/index.css +1 -1
- package/package.json +4 -4
- package/src/chat.tsx +19 -2
- 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 +8 -3
- 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 +80 -43
- 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 +26 -2
- package/src/components/biz-comp/suggestions.tsx +5 -1
- package/src/components/bs-ui/attachment-part-group.tsx +5 -2
- package/src/components/bs-ui/attachment-part.tsx +14 -9
- package/src/components/bs-ui/attachments-previewer.tsx +6 -3
- package/src/components/bs-ui/base-button.tsx +20 -5
- package/src/components/bs-ui/border-animation.tsx +107 -0
- package/src/components/bs-ui/bs-icons.tsx +35 -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/confirm-dialog.tsx +17 -11
- package/src/components/bs-ui/fields-design-info-table.tsx +160 -0
- package/src/components/bs-ui/fields-previewer.tsx +18 -8
- 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 +4 -2
- package/src/components/bs-ui/line-checker.tsx +19 -5
- package/src/components/bs-ui/previewer-header.tsx +48 -4
- package/src/components/bs-ui/primary-entry-btn.tsx +2 -1
- 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/index.tsx +0 -1
- package/src/lib/parse-design-doc.ts +60 -0
- package/src/lib/utils.ts +79 -2
- package/src/plugins/form-builder-base-plugin/const.ts +3 -0
- package/src/plugins/form-builder-plugin/components/create-form-confirm.tsx +12 -1
- package/src/plugins/form-builder-plugin/components/design-doc-part.tsx +19 -0
- 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/fields-part.tsx +78 -0
- package/src/plugins/form-builder-plugin/components/follow-up.tsx +21 -6
- package/src/plugins/form-builder-plugin/components/msg-part.tsx +20 -145
- package/src/plugins/form-builder-plugin/components/opening-lines.tsx +11 -6
- package/src/plugins/form-builder-plugin/components/suggestion-part.tsx +62 -0
- package/src/plugins/form-builder-plugin/hooks/index.tsx +50 -0
- package/src/plugins/form-builder-plugin/index.ts +91 -14
- package/src/plugins/form-builder-plugin/types.ts +22 -2
- package/src/plugins/form-builder-plugin/utils/get-render-strategy.ts +27 -0
- package/src/plugins/form-builder-plugin/utils/index.ts +75 -41
- package/src/plugins/form-filling-plugin/components/FormFillingOpeningLines.tsx +4 -0
- package/src/plugins/form-filling-plugin/components/batch-fill-part.tsx +17 -0
- package/src/plugins/form-filling-plugin/components/batch-generator-action.tsx +50 -35
- package/src/plugins/form-filling-plugin/components/entry-btn.tsx +1 -1
- package/src/plugins/form-filling-plugin/components/first-batch-generating-animation.tsx +11 -0
- package/src/plugins/form-filling-plugin/components/generated-data-counter.tsx +17 -0
- package/src/plugins/form-filling-plugin/components/msg-part.tsx +39 -122
- package/src/plugins/form-filling-plugin/components/non-first-batch-generating-animation.tsx +18 -0
- package/src/plugins/form-filling-plugin/components/single-fill-part.tsx +42 -0
- package/src/plugins/form-filling-plugin/hooks/use-conversation-id-in-ctx.ts +13 -0
- package/src/plugins/form-filling-plugin/hooks/use-fields-data.ts +110 -0
- package/src/plugins/form-filling-plugin/index.ts +62 -42
- package/src/plugins/form-filling-plugin/types.ts +21 -1
- package/src/plugins/report-query-plugin/components/query-msg-part.tsx +25 -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 +41 -5
- package/src/plugins/report-query-plugin/types.ts +6 -0
- package/src/sdk.impl.tsx +4 -0
- package/src/store/index.ts +11 -1
- package/src/stories/BorderAnimation.stories.tsx +116 -0
- package/src/stories/FormInfoEditor.stories.tsx +19 -28
- package/src/stories/PreviewerHeader.stories.tsx +24 -0
- package/src/stories/fields-design-info-table.stories.tsx +203 -0
- package/src/style.css +25 -0
- package/src/plugins/form-builder-plugin/hooks/index.ts +0 -0
- package/src/plugins/general-model-form-builder-plugin/components/confirmer.tsx +0 -90
- package/src/plugins/general-model-form-builder-plugin/components/ghost-evt-dispatcher.tsx +0 -69
- package/src/plugins/general-model-form-builder-plugin/components/msg-part.tsx +0 -147
- package/src/plugins/general-model-form-builder-plugin/components/new-confirmer.tsx +0 -191
- package/src/plugins/general-model-form-builder-plugin/const.ts +0 -3
- package/src/plugins/general-model-form-builder-plugin/index.ts +0 -20
- package/src/plugins/general-model-form-builder-plugin/types.ts +0 -1
|
@@ -18,6 +18,7 @@ import { FormFillingOpeningLines } from './components/FormFillingOpeningLines';
|
|
|
18
18
|
import { FillMessagePart } from './components/msg-part';
|
|
19
19
|
import { UIDataTypes, UIMessagePart, UITools } from 'ai';
|
|
20
20
|
import {
|
|
21
|
+
ensureEndSlash,
|
|
21
22
|
extractTextPartMeta,
|
|
22
23
|
IsFieldsJsonPart,
|
|
23
24
|
mergeConsecutiveTargets,
|
|
@@ -74,26 +75,11 @@ export class FormFillingPlugin extends ChatAreaPlugin<FormFillingPluginCtx> {
|
|
|
74
75
|
this.handleFillModeUpdate
|
|
75
76
|
);
|
|
76
77
|
|
|
77
|
-
sdk.eventBus.on<'chat-area-visibility-change'>(
|
|
78
|
-
'chat-area-visibility-change',
|
|
79
|
-
this.handleChatAreaVisibilityChange
|
|
80
|
-
);
|
|
81
|
-
|
|
82
78
|
// this.handleFormStructureReady({
|
|
83
79
|
// fields: MOCK_FORM_STRUCTURE,
|
|
84
80
|
// });
|
|
85
81
|
};
|
|
86
82
|
|
|
87
|
-
private handleChatAreaVisibilityChange: EventHandler<{ visible: boolean }> = ({
|
|
88
|
-
visible,
|
|
89
|
-
}: {
|
|
90
|
-
visible: boolean;
|
|
91
|
-
}) => {
|
|
92
|
-
if (!visible) {
|
|
93
|
-
this.lifecycleHooks?.onBeforeMessagesClear?.();
|
|
94
|
-
}
|
|
95
|
-
};
|
|
96
|
-
|
|
97
83
|
private handleFillModeUpdate: EventHandler<{ mode: FormFillingMode }> = ({
|
|
98
84
|
mode,
|
|
99
85
|
}: {
|
|
@@ -102,6 +88,18 @@ export class FormFillingPlugin extends ChatAreaPlugin<FormFillingPluginCtx> {
|
|
|
102
88
|
this.Context!.fillMode = mode;
|
|
103
89
|
};
|
|
104
90
|
|
|
91
|
+
public getCount = (messageId: string): number => {
|
|
92
|
+
console.log('get count', messageId, this.Context.counterMap.get(messageId));
|
|
93
|
+
return this.Context.counterMap.get(messageId) || 0;
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
public setCount = (messageId: string, inc: number) => {
|
|
97
|
+
const existingCount = this.Context.counterMap.get(messageId) || 0;
|
|
98
|
+
const newCount = existingCount + inc;
|
|
99
|
+
console.log('set count', messageId, newCount);
|
|
100
|
+
this.Context.counterMap.set(messageId, newCount);
|
|
101
|
+
};
|
|
102
|
+
|
|
105
103
|
public dispose?: (() => void) | undefined = () => {
|
|
106
104
|
this.batchFillingDataManager.dispose();
|
|
107
105
|
|
|
@@ -114,11 +112,6 @@ export class FormFillingPlugin extends ChatAreaPlugin<FormFillingPluginCtx> {
|
|
|
114
112
|
FILLING_EVENTS.FORM_FILLING_MODE_UPDATE,
|
|
115
113
|
this.handleFillModeUpdate
|
|
116
114
|
);
|
|
117
|
-
|
|
118
|
-
this.sdkInst.eventBus.off<'chat-area-visibility-change'>(
|
|
119
|
-
'chat-area-visibility-change',
|
|
120
|
-
this.handleChatAreaVisibilityChange
|
|
121
|
-
);
|
|
122
115
|
};
|
|
123
116
|
|
|
124
117
|
private handleFormStructureReady: EventHandler<FormStructure> = (params: FormStructure) => {
|
|
@@ -144,7 +137,38 @@ export class FormFillingPlugin extends ChatAreaPlugin<FormFillingPluginCtx> {
|
|
|
144
137
|
});
|
|
145
138
|
};
|
|
146
139
|
|
|
140
|
+
private clearHistoryConversation = async (conversationId: string) => {
|
|
141
|
+
const apiEndpoint = this.sdkInst?.options.backendApiEndpoint;
|
|
142
|
+
if (!apiEndpoint) {
|
|
143
|
+
console.error('Backend API endpoint is not defined in SDK options.');
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (!conversationId) {
|
|
148
|
+
console.error('Conversation ID is required to clear history.');
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
await fetch(`${ensureEndSlash(apiEndpoint)}form/conversation/clear`, {
|
|
153
|
+
method: 'POST',
|
|
154
|
+
body: JSON.stringify({ conversationId }),
|
|
155
|
+
});
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
public clearBatchFilledData = () => {
|
|
159
|
+
this.clearHistoryConversation(this.Context.conversationId);
|
|
160
|
+
this.sdkInst.clearChatHistory();
|
|
161
|
+
this.batchFillingDataManager.clear();
|
|
162
|
+
};
|
|
163
|
+
|
|
147
164
|
public lifecycleHooks?: PluginHooks | undefined = {
|
|
165
|
+
onAfterChatAreaHide: ({ clearMsgs }) => {
|
|
166
|
+
// reset to AI mode when chat area is hidden
|
|
167
|
+
clearMsgs?.();
|
|
168
|
+
this.Context.fillMode = 'AI';
|
|
169
|
+
this.Context.counterMap.clear();
|
|
170
|
+
this.clearHistoryConversation(this.Context.conversationId);
|
|
171
|
+
},
|
|
148
172
|
onBeforeChatRender: () => {
|
|
149
173
|
return {
|
|
150
174
|
enableMessageMerge: true,
|
|
@@ -163,39 +187,31 @@ export class FormFillingPlugin extends ChatAreaPlugin<FormFillingPluginCtx> {
|
|
|
163
187
|
onBeforeMessagePartsRender: (parts: Array<part>) => {
|
|
164
188
|
// todo: reduce loops
|
|
165
189
|
const mergedParts = mergeParts(parts as UIMessagePart<UIDataTypes, UITools>[], (p0, p1) => {
|
|
190
|
+
if (p0.type !== p1.type) {
|
|
191
|
+
return false;
|
|
192
|
+
}
|
|
193
|
+
|
|
166
194
|
if (Array.isArray(p0) || Array.isArray(p1)) {
|
|
167
195
|
return false;
|
|
168
196
|
}
|
|
169
197
|
|
|
170
198
|
const meta0 = extractTextPartMeta(p0);
|
|
171
199
|
const meta1 = extractTextPartMeta(p1);
|
|
172
|
-
return meta0?.field?.fieldName == meta1?.field?.fieldName;
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
return mergeConsecutiveTargets<part>(mergedParts, IsFieldsJsonPart) as part[];
|
|
176
|
-
},
|
|
177
|
-
onBeforeMessagesClear: () => {
|
|
178
|
-
const conversationId = this.Context?.conversationId || '';
|
|
179
|
-
if (!conversationId) {
|
|
180
|
-
return;
|
|
181
|
-
}
|
|
182
200
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
method: 'POST',
|
|
186
|
-
body: JSON.stringify({ conversationId }),
|
|
187
|
-
});
|
|
201
|
+
const fieldName0 = meta0?.field?.fieldName;
|
|
202
|
+
const fieldName1 = meta1?.field?.fieldName;
|
|
188
203
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
if (keepCtx) {
|
|
192
|
-
return;
|
|
204
|
+
if (!fieldName0 || !fieldName1) {
|
|
205
|
+
return false;
|
|
193
206
|
}
|
|
194
207
|
|
|
195
|
-
|
|
196
|
-
};
|
|
208
|
+
return fieldName0 === fieldName1;
|
|
209
|
+
});
|
|
197
210
|
|
|
198
|
-
|
|
211
|
+
return mergeConsecutiveTargets<part>(mergedParts, IsFieldsJsonPart) as part[];
|
|
212
|
+
},
|
|
213
|
+
onBeforeMessagesClear: (id) => {
|
|
214
|
+
this.clearHistoryConversation(id!);
|
|
199
215
|
},
|
|
200
216
|
onBeforeMessageSend: (ctx) => {
|
|
201
217
|
const formStructure = Array.from(this.Context?.fieldMap.values() || []);
|
|
@@ -216,6 +232,9 @@ export class FormFillingPlugin extends ChatAreaPlugin<FormFillingPluginCtx> {
|
|
|
216
232
|
},
|
|
217
233
|
};
|
|
218
234
|
},
|
|
235
|
+
onAfterMessageSend: (_) => {
|
|
236
|
+
this.sdkInst?.setGlobalLoadingMessage('正在处理');
|
|
237
|
+
},
|
|
219
238
|
};
|
|
220
239
|
}
|
|
221
240
|
|
|
@@ -229,6 +248,7 @@ export const FormFillingPluginRegisterEntry: PluginRegistryEntry<FormFillingPlug
|
|
|
229
248
|
subFieldsNameMap: new Map(),
|
|
230
249
|
conversationId: '',
|
|
231
250
|
fillMode: 'AI',
|
|
251
|
+
counterMap: new Map(),
|
|
232
252
|
};
|
|
233
253
|
},
|
|
234
254
|
};
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { FormFillingMode } from '@baishuyun/types';
|
|
1
|
+
import { FormFillingMode, MsgPartCompProps } from '@baishuyun/types';
|
|
2
2
|
import { Field } from '../form-builder-base-plugin/types';
|
|
3
|
+
import { TextUIPart } from 'ai';
|
|
4
|
+
import { FieldValueCheckerProps } from '@/components/biz-comp/FieldValueChecker';
|
|
3
5
|
|
|
4
6
|
export interface FormFillingPluginCtx {
|
|
5
7
|
fieldMap: Map<string, Field>;
|
|
@@ -11,4 +13,22 @@ export interface FormFillingPluginCtx {
|
|
|
11
13
|
conversationId: string;
|
|
12
14
|
|
|
13
15
|
fillMode: FormFillingMode;
|
|
16
|
+
|
|
17
|
+
counterMap: Map<string, number>; // key is messageId, value is row counter
|
|
14
18
|
}
|
|
19
|
+
|
|
20
|
+
export type FillPartRenderStrategy =
|
|
21
|
+
| 'batch' // 批量填写模式渲染
|
|
22
|
+
| 'single' // 单条填写模式渲染
|
|
23
|
+
| 'markdown' // markdown 内容渲染,通用行为
|
|
24
|
+
| 'unknown'; // 未知类型,null
|
|
25
|
+
|
|
26
|
+
export interface IFieldsData {
|
|
27
|
+
fieldsParts: TextUIPart[];
|
|
28
|
+
filledFields: Array<FieldValueCheckerProps>;
|
|
29
|
+
fieldPropsArray: Array<FieldValueCheckerProps | null>;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export type FillPartRenderStrategyMap = {
|
|
33
|
+
[key in FillPartRenderStrategy]: React.FC<MsgPartCompProps & IFieldsData>;
|
|
34
|
+
};
|
|
@@ -7,11 +7,9 @@ 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
|
|
|
12
|
+
// TODO: refactor with strategy pattern;
|
|
15
13
|
export const QueryMsgPart = ({ part, ...rest }: MsgPartCompProps) => {
|
|
16
14
|
const textPart = part as TextUIPart;
|
|
17
15
|
const ctx = usePluginCtx<IReportQueryContext, ReportQueryPlugin>(PLUGIN_NAME);
|
|
@@ -29,25 +27,34 @@ export const QueryMsgPart = ({ part, ...rest }: MsgPartCompProps) => {
|
|
|
29
27
|
|
|
30
28
|
if (result.isAggregate) {
|
|
31
29
|
return (
|
|
32
|
-
<
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
<AggregateTableIcon />
|
|
38
|
-
</span>
|
|
39
|
-
}
|
|
40
|
-
title={result.title!}
|
|
41
|
-
disableExpand
|
|
42
|
-
/>
|
|
43
|
-
</FakeBotMessage>
|
|
30
|
+
<CreatedSourceMsg
|
|
31
|
+
type={'aggregate'}
|
|
32
|
+
title={result.title || ''}
|
|
33
|
+
done={textPart.state === 'done'}
|
|
34
|
+
/>
|
|
44
35
|
);
|
|
45
36
|
}
|
|
46
37
|
|
|
47
|
-
console.log('
|
|
38
|
+
console.log('queryResult', result);
|
|
39
|
+
|
|
48
40
|
ctx.queryResult = result;
|
|
49
41
|
ctx.queryResult.appID = ctx.appInfo?.appId || '';
|
|
50
|
-
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<>
|
|
45
|
+
{result.source && result.source !== 'aggregate' ? (
|
|
46
|
+
<CreatedSourceMsg
|
|
47
|
+
type={result.source}
|
|
48
|
+
title={result.title || ''}
|
|
49
|
+
done={textPart.state === 'done'}
|
|
50
|
+
/>
|
|
51
|
+
) : null}
|
|
52
|
+
<DataTableCard
|
|
53
|
+
{...(result || {})}
|
|
54
|
+
streaming={textPart?.state === 'streaming'}
|
|
55
|
+
></DataTableCard>
|
|
56
|
+
</>
|
|
57
|
+
);
|
|
51
58
|
}
|
|
52
59
|
|
|
53
60
|
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,
|
|
@@ -12,8 +13,15 @@ import { QueryEntryBtn } from './components/query-entry-btn';
|
|
|
12
13
|
import { QueryAvatar } from './components/avatar';
|
|
13
14
|
import { QueryMsgPart } from './components/query-msg-part';
|
|
14
15
|
import { queryResult2createParams, queryResult2previewerProps } from './utils';
|
|
16
|
+
import { ensureEndSlash } from '@/lib/utils';
|
|
15
17
|
|
|
16
18
|
export class ReportQueryPlugin extends ChatAreaPlugin<IReportQueryContext> {
|
|
19
|
+
private _inst: IChatSDK | null = null;
|
|
20
|
+
|
|
21
|
+
public init?: ((sdk: IChatSDK) => void) | undefined = (sdkInst: IChatSDK) => {
|
|
22
|
+
this._inst = sdkInst;
|
|
23
|
+
};
|
|
24
|
+
|
|
17
25
|
public pluginName: string = PLUGIN_NAME;
|
|
18
26
|
|
|
19
27
|
public customComponents?: Partial<PluginCustomComponent> | undefined = {
|
|
@@ -24,8 +32,12 @@ export class ReportQueryPlugin extends ChatAreaPlugin<IReportQueryContext> {
|
|
|
24
32
|
};
|
|
25
33
|
|
|
26
34
|
public lifecycleHooks?: PluginHooks | undefined = {
|
|
35
|
+
onBeforeMessagesClear: (conversationId) => {
|
|
36
|
+
this.clearHistoryConversation(conversationId || '');
|
|
37
|
+
},
|
|
38
|
+
|
|
27
39
|
onAfterChatAreaHide: ({ clearMsgs }) => {
|
|
28
|
-
|
|
40
|
+
clearMsgs();
|
|
29
41
|
},
|
|
30
42
|
|
|
31
43
|
onBeforeChatRender: () => {
|
|
@@ -43,11 +55,15 @@ export class ReportQueryPlugin extends ChatAreaPlugin<IReportQueryContext> {
|
|
|
43
55
|
},
|
|
44
56
|
};
|
|
45
57
|
},
|
|
58
|
+
|
|
59
|
+
onAfterMessageSend: (_) => {
|
|
60
|
+
console.log('enter onAfterMessageSend hook in ReportQueryPlugin');
|
|
61
|
+
this.setLoadingMsg('正在处理');
|
|
62
|
+
},
|
|
46
63
|
};
|
|
47
64
|
|
|
48
65
|
public getPreviewerProps = (entryId: string) => {
|
|
49
66
|
if (!this.Context.queryResult) {
|
|
50
|
-
console.log('No query result in context');
|
|
51
67
|
return null;
|
|
52
68
|
}
|
|
53
69
|
|
|
@@ -56,7 +72,6 @@ export class ReportQueryPlugin extends ChatAreaPlugin<IReportQueryContext> {
|
|
|
56
72
|
|
|
57
73
|
public getCreateParams = (entryId: string) => {
|
|
58
74
|
if (!this.Context.queryResult) {
|
|
59
|
-
console.log('No query result in context');
|
|
60
75
|
return null;
|
|
61
76
|
}
|
|
62
77
|
|
|
@@ -92,14 +107,35 @@ export class ReportQueryPlugin extends ChatAreaPlugin<IReportQueryContext> {
|
|
|
92
107
|
console.log('forms received in plugin:', formMap);
|
|
93
108
|
};
|
|
94
109
|
|
|
110
|
+
private clearHistoryConversation = async (conversationId: string, inst?: IChatSDK) => {
|
|
111
|
+
const apiEndpoint = (inst || this._inst)?.options.backendApiEndpoint;
|
|
112
|
+
if (!apiEndpoint) {
|
|
113
|
+
console.error('Backend API endpoint is not defined in SDK options.');
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (!conversationId) {
|
|
118
|
+
console.error('Conversation ID is required to clear history.');
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
await fetch(`${ensureEndSlash(apiEndpoint)}/form/conversation/clear`, {
|
|
123
|
+
method: 'POST',
|
|
124
|
+
body: JSON.stringify({ conversationId }),
|
|
125
|
+
});
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
private setLoadingMsg = (message: string) => {
|
|
129
|
+
this._inst?.setGlobalLoadingMessage(message);
|
|
130
|
+
};
|
|
131
|
+
|
|
95
132
|
public constructor(ctx: IReportQueryContext) {
|
|
96
133
|
super(ctx);
|
|
97
134
|
this.Context = ctx;
|
|
98
135
|
}
|
|
99
136
|
|
|
100
137
|
public clearCtx = () => {
|
|
101
|
-
|
|
102
|
-
// this.Context.queryResult = undefined;
|
|
138
|
+
this.Context.queryResult = undefined;
|
|
103
139
|
};
|
|
104
140
|
}
|
|
105
141
|
|
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,
|
|
@@ -107,7 +118,6 @@ export const setupStoreSubscriptions = (store: ChatStore, option: IChatSDKOption
|
|
|
107
118
|
option.onChatStatusChange?.(status);
|
|
108
119
|
// @deprecated, will be removed in future versions
|
|
109
120
|
eventBus.emit('chat-area-visibility-change', { visible, status });
|
|
110
|
-
console.log('chat status changed:', status);
|
|
111
121
|
}
|
|
112
122
|
);
|
|
113
123
|
};
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
|
|
3
|
+
import { BorderAnimation } from '@/components/bs-ui/border-animation';
|
|
4
|
+
|
|
5
|
+
const meta = {
|
|
6
|
+
title: 'Animation/BorderAnimation',
|
|
7
|
+
component: BorderAnimation,
|
|
8
|
+
tags: ['autodocs'],
|
|
9
|
+
parameters: {
|
|
10
|
+
layout: 'centered',
|
|
11
|
+
},
|
|
12
|
+
args: {},
|
|
13
|
+
} satisfies Meta<typeof BorderAnimation>;
|
|
14
|
+
|
|
15
|
+
export default meta;
|
|
16
|
+
type Story = StoryObj<typeof meta>;
|
|
17
|
+
|
|
18
|
+
export const Default: Story = {
|
|
19
|
+
args: {
|
|
20
|
+
children: (
|
|
21
|
+
<div className="flex items-center gap-[6px] bg-white px-[10px] py-[4px] rounded-[4px]">
|
|
22
|
+
<span className="text-[#999] text-[14px]">
|
|
23
|
+
数据生成中,可点击下方按钮暂停
|
|
24
|
+
</span>
|
|
25
|
+
</div>
|
|
26
|
+
),
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const WithCustomContent: Story = {
|
|
31
|
+
args: {
|
|
32
|
+
children: (
|
|
33
|
+
<div className="bg-white px-4 py-3 rounded-[4px]">
|
|
34
|
+
<h3 className="text-[16px] font-medium text-[#333]">标题内容</h3>
|
|
35
|
+
<p className="text-[14px] text-[#666] mt-1">
|
|
36
|
+
这是一段描述文字,展示边框动画效果。
|
|
37
|
+
</p>
|
|
38
|
+
</div>
|
|
39
|
+
),
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export const LargerRadius: Story = {
|
|
44
|
+
args: {
|
|
45
|
+
borderRadius: 12,
|
|
46
|
+
children: (
|
|
47
|
+
<div className="bg-white px-4 py-3 rounded-[12px]">
|
|
48
|
+
<p className="text-[14px] text-[#666]">圆角 12px 的边框动画</p>
|
|
49
|
+
</div>
|
|
50
|
+
),
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export const SlowAnimation: Story = {
|
|
55
|
+
args: {
|
|
56
|
+
duration: 5,
|
|
57
|
+
children: (
|
|
58
|
+
<div className="bg-white px-4 py-3 rounded-[4px]">
|
|
59
|
+
<p className="text-[14px] text-[#666]">慢速动画(5秒一圈)</p>
|
|
60
|
+
</div>
|
|
61
|
+
),
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
export const FastAnimation: Story = {
|
|
66
|
+
args: {
|
|
67
|
+
duration: 1,
|
|
68
|
+
children: (
|
|
69
|
+
<div className="bg-white px-4 py-3 rounded-[4px]">
|
|
70
|
+
<p className="text-[14px] text-[#666]">快速动画(1秒一圈)</p>
|
|
71
|
+
</div>
|
|
72
|
+
),
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
export const CustomGradient: Story = {
|
|
77
|
+
args: {
|
|
78
|
+
gradient:
|
|
79
|
+
'linear-gradient(180deg, #FF84B4 0%, #FF0265 50%, #FFB1FA 100%)',
|
|
80
|
+
children: (
|
|
81
|
+
<div className="bg-white px-4 py-3 rounded-[4px]">
|
|
82
|
+
<p className="text-[14px] text-[#666]">自定义渐变色(粉色系)</p>
|
|
83
|
+
</div>
|
|
84
|
+
),
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
export const CustomClassName: Story = {
|
|
89
|
+
args: {
|
|
90
|
+
className: 'w-[300px]',
|
|
91
|
+
children: (
|
|
92
|
+
<div className="bg-white px-4 py-3 rounded-[4px]">
|
|
93
|
+
<p className="text-[14px] text-[#666]">自定义宽度 300px</p>
|
|
94
|
+
</div>
|
|
95
|
+
),
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
export const FullWidth: Story = {
|
|
100
|
+
decorators: [
|
|
101
|
+
(Story) => (
|
|
102
|
+
<div style={{ width: '500px' }}>
|
|
103
|
+
<Story />
|
|
104
|
+
</div>
|
|
105
|
+
),
|
|
106
|
+
],
|
|
107
|
+
args: {
|
|
108
|
+
children: (
|
|
109
|
+
<div className="bg-white px-4 py-3 rounded-[4px]">
|
|
110
|
+
<p className="text-[14px] text-[#666]">
|
|
111
|
+
宽度 100%,自动填满父容器
|
|
112
|
+
</p>
|
|
113
|
+
</div>
|
|
114
|
+
),
|
|
115
|
+
},
|
|
116
|
+
};
|