@agentscope-ai/chat 1.1.60 → 1.1.61-beta.1775617662658
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/components/Bubble/BubbleList.tsx +66 -9
- package/components/ChatAnywhere/Chat/index.tsx +35 -1
- package/components/ChatAnywhere/Input/index.tsx +1 -0
- package/components/ChatAnywhere/hooks/ChatAnywhereProvider.tsx +5 -0
- package/components/ChatAnywhere/hooks/types.ts +18 -0
- package/components/Sender/index.tsx +6 -0
- package/lib/Bubble/BubbleList.d.ts +5 -0
- package/lib/Bubble/BubbleList.js +93 -25
- package/lib/ChatAnywhere/Chat/index.js +66 -2
- package/lib/ChatAnywhere/Input/index.js +1 -0
- package/lib/ChatAnywhere/hooks/ChatAnywhereProvider.d.ts +5 -0
- package/lib/ChatAnywhere/hooks/types.d.ts +18 -0
- package/lib/Sender/index.d.ts +5 -0
- package/lib/Sender/index.js +1 -1
- package/package.json +1 -1
- package/components/AgentScopeRuntimeWebUI/bailian-high-code-webui/README.md +0 -75
- package/components/AgentScopeRuntimeWebUI/bailian-high-code-webui/eslint.config.js +0 -28
- package/components/AgentScopeRuntimeWebUI/bailian-high-code-webui/index.html +0 -12
- package/components/AgentScopeRuntimeWebUI/bailian-high-code-webui/package.json +0 -34
- package/components/AgentScopeRuntimeWebUI/bailian-high-code-webui/src/App.tsx +0 -20
- package/components/AgentScopeRuntimeWebUI/bailian-high-code-webui/src/components/Cards/Weather.tsx +0 -234
- package/components/AgentScopeRuntimeWebUI/bailian-high-code-webui/src/components/Chat/defaultConfig.ts +0 -54
- package/components/AgentScopeRuntimeWebUI/bailian-high-code-webui/src/components/Chat/index.tsx +0 -11
- package/components/AgentScopeRuntimeWebUI/bailian-high-code-webui/src/main.tsx +0 -9
- package/components/AgentScopeRuntimeWebUI/bailian-high-code-webui/src/vite-env.d.ts +0 -4
- package/components/AgentScopeRuntimeWebUI/bailian-high-code-webui/tsconfig.app.json +0 -24
- package/components/AgentScopeRuntimeWebUI/bailian-high-code-webui/tsconfig.json +0 -7
- package/components/AgentScopeRuntimeWebUI/bailian-high-code-webui/tsconfig.node.json +0 -22
- package/components/AgentScopeRuntimeWebUI/bailian-high-code-webui/vite.config.ts +0 -7
|
@@ -3,9 +3,9 @@ import type { BubbleProps } from './interface';
|
|
|
3
3
|
import ScrollToBottom from './ScrollToBottom';
|
|
4
4
|
import Style from './style/list';
|
|
5
5
|
import { useProviderContext } from '@agentscope-ai/chat';
|
|
6
|
-
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
|
6
|
+
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
7
7
|
import cls from 'classnames';
|
|
8
|
-
import { useInViewport,
|
|
8
|
+
import { useInViewport, usePrevious } from 'ahooks';
|
|
9
9
|
import { usePaginationItems } from './hooks/usePaginationItemsData';
|
|
10
10
|
import { Spin } from 'antd';
|
|
11
11
|
|
|
@@ -45,6 +45,9 @@ export interface BubbleListProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
45
45
|
};
|
|
46
46
|
pagination?: boolean;
|
|
47
47
|
order?: 'asc' | 'desc';
|
|
48
|
+
onLoadMore?: () => Promise<{ noMore: boolean }>;
|
|
49
|
+
onLoadMoreStart?: () => void;
|
|
50
|
+
onLoadMoreEnd?: () => void;
|
|
48
51
|
}
|
|
49
52
|
|
|
50
53
|
interface BubbleListContentProps {
|
|
@@ -55,16 +58,30 @@ interface BubbleListContentProps {
|
|
|
55
58
|
scrollRef: React.RefObject<HTMLElement | null>;
|
|
56
59
|
listClassName?: string;
|
|
57
60
|
children?: React.ReactNode | React.ReactNode[];
|
|
61
|
+
onLoadMoreStart?: () => void;
|
|
62
|
+
onLoadMoreEnd?: () => void;
|
|
58
63
|
}
|
|
59
64
|
|
|
60
|
-
function BubbleListContent(
|
|
65
|
+
function BubbleListContent(props: BubbleListContentProps) {
|
|
66
|
+
const { order, paginationItems, noMore, loadMore, scrollRef, children, onLoadMoreStart, onLoadMoreEnd } = props;
|
|
61
67
|
const handleLoadMore = useCallback(() => {
|
|
62
68
|
return loadMore(scrollRef);
|
|
63
69
|
}, [loadMore, scrollRef]);
|
|
64
70
|
|
|
71
|
+
const moreUI = useMemo(() => {
|
|
72
|
+
if (noMore) return null;
|
|
73
|
+
return (
|
|
74
|
+
<LoadMore
|
|
75
|
+
handleLoadMore={handleLoadMore}
|
|
76
|
+
onLoadMoreStart={onLoadMoreStart}
|
|
77
|
+
onLoadMoreEnd={onLoadMoreEnd}
|
|
78
|
+
/>
|
|
79
|
+
);
|
|
80
|
+
}, [handleLoadMore, onLoadMoreStart, onLoadMoreEnd, noMore]);
|
|
81
|
+
|
|
65
82
|
return (
|
|
66
83
|
<>
|
|
67
|
-
{order === 'asc' && !noMore ?
|
|
84
|
+
{order === 'asc' && !noMore ? moreUI : null}
|
|
68
85
|
{children ? children : paginationItems.map(({ key, ...bubble }, index) => {
|
|
69
86
|
const isLast = index === paginationItems.length - 1;
|
|
70
87
|
return (
|
|
@@ -75,12 +92,18 @@ function BubbleListContent({ order, paginationItems, noMore, loadMore, scrollRef
|
|
|
75
92
|
/>
|
|
76
93
|
)
|
|
77
94
|
})}
|
|
78
|
-
{order === 'desc' && !noMore ?
|
|
95
|
+
{order === 'desc' && !noMore ? moreUI : null}
|
|
79
96
|
</>
|
|
80
97
|
);
|
|
81
98
|
}
|
|
82
99
|
|
|
83
|
-
|
|
100
|
+
interface LoadMoreProps {
|
|
101
|
+
handleLoadMore: () => Promise<void>;
|
|
102
|
+
onLoadMoreStart?: () => void;
|
|
103
|
+
onLoadMoreEnd?: () => void;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function LoadMore({ handleLoadMore, onLoadMoreStart, onLoadMoreEnd }: LoadMoreProps) {
|
|
84
107
|
const ref = useRef(null);
|
|
85
108
|
const [inViewport] = useInViewport(ref)
|
|
86
109
|
const [loading, setLoading] = useState(false)
|
|
@@ -92,13 +115,15 @@ function LoadMore({ handleLoadMore }: { handleLoadMore: () => Promise<void> }) {
|
|
|
92
115
|
if (inViewport && previousInViewport === undefined) return;
|
|
93
116
|
if (loading) return;
|
|
94
117
|
if (inViewport) {
|
|
118
|
+
onLoadMoreStart?.();
|
|
95
119
|
setLoading(true);
|
|
96
120
|
handleLoadMore().finally(() => {
|
|
97
121
|
setLoading(false);
|
|
122
|
+
onLoadMoreEnd?.();
|
|
98
123
|
});
|
|
99
124
|
}
|
|
100
125
|
|
|
101
|
-
}, [previousInViewport, inViewport, loading, handleLoadMore])
|
|
126
|
+
}, [previousInViewport, inViewport, loading, handleLoadMore, onLoadMoreStart, onLoadMoreEnd])
|
|
102
127
|
|
|
103
128
|
return <div ref={ref} className={`${prefixCls}-load-more`}><Spin spinning={true} /></div>
|
|
104
129
|
}
|
|
@@ -108,6 +133,7 @@ const BubbleList: React.ForwardRefRenderFunction<BubbleListRef, BubbleListProps>
|
|
|
108
133
|
items = [],
|
|
109
134
|
order = 'asc',
|
|
110
135
|
} = props;
|
|
136
|
+
const [serverNoMore, setServerNoMore] = useState(false);
|
|
111
137
|
|
|
112
138
|
const [showScrollToBottom, setShowScrollToBottom] = useState(false);
|
|
113
139
|
const scrollRef = React.useRef<HTMLDivElement | null>(null);
|
|
@@ -169,10 +195,39 @@ const BubbleList: React.ForwardRefRenderFunction<BubbleListRef, BubbleListProps>
|
|
|
169
195
|
}), [scrollToBottom]);
|
|
170
196
|
|
|
171
197
|
|
|
172
|
-
const
|
|
173
|
-
|
|
198
|
+
const enableServerPagination = Boolean(props.pagination && props.onLoadMore);
|
|
199
|
+
const { items: localPaginationItems, noMore: localNoMore, loadMore: localLoadMore } = usePaginationItems(items, {
|
|
200
|
+
enable: Boolean(props.pagination && !enableServerPagination),
|
|
174
201
|
order,
|
|
175
202
|
});
|
|
203
|
+
const loadMoreFromServer = useCallback(async (innerScrollRef?: React.RefObject<HTMLElement | null>) => {
|
|
204
|
+
const scrollEl = innerScrollRef?.current;
|
|
205
|
+
const prevScrollHeight = scrollEl?.scrollHeight ?? 0;
|
|
206
|
+
const result = await props.onLoadMore?.();
|
|
207
|
+
await new Promise<void>((resolve) => requestAnimationFrame(() => resolve()));
|
|
208
|
+
|
|
209
|
+
if (scrollEl) {
|
|
210
|
+
const newScrollHeight = scrollEl.scrollHeight;
|
|
211
|
+
scrollEl.scrollTop += newScrollHeight - prevScrollHeight;
|
|
212
|
+
}
|
|
213
|
+
setServerNoMore(Boolean(result?.noMore));
|
|
214
|
+
}, [props.onLoadMore]);
|
|
215
|
+
|
|
216
|
+
const paginationItems = enableServerPagination ? items : localPaginationItems;
|
|
217
|
+
const noMore = enableServerPagination ? serverNoMore : localNoMore;
|
|
218
|
+
const loadMore = enableServerPagination ? loadMoreFromServer : localLoadMore;
|
|
219
|
+
|
|
220
|
+
useEffect(() => {
|
|
221
|
+
if (!enableServerPagination) return;
|
|
222
|
+
if (items.length === 0) {
|
|
223
|
+
setServerNoMore(false);
|
|
224
|
+
}
|
|
225
|
+
}, [enableServerPagination, items.length]);
|
|
226
|
+
|
|
227
|
+
useEffect(() => {
|
|
228
|
+
if (!enableServerPagination) return;
|
|
229
|
+
setServerNoMore(false);
|
|
230
|
+
}, [enableServerPagination, props.onLoadMore]);
|
|
176
231
|
|
|
177
232
|
useEffect(() => {
|
|
178
233
|
scrollToBottom('auto');
|
|
@@ -218,6 +273,8 @@ const BubbleList: React.ForwardRefRenderFunction<BubbleListRef, BubbleListProps>
|
|
|
218
273
|
noMore={noMore}
|
|
219
274
|
loadMore={loadMore}
|
|
220
275
|
scrollRef={scrollRef as React.RefObject<HTMLElement | null>}
|
|
276
|
+
onLoadMoreStart={props.onLoadMoreStart}
|
|
277
|
+
onLoadMoreEnd={props.onLoadMoreEnd}
|
|
221
278
|
>
|
|
222
279
|
{props.children}
|
|
223
280
|
</BubbleListContent>
|
|
@@ -10,15 +10,46 @@ import Style from './style';
|
|
|
10
10
|
|
|
11
11
|
export default forwardRef(function (_, ref) {
|
|
12
12
|
const messages = useChatAnywhere(v => v.messages);
|
|
13
|
+
const setMessages = useChatAnywhere(v => v.setMessages);
|
|
14
|
+
const onLoadMore = useChatAnywhere(v => v.onLoadMore);
|
|
13
15
|
const safeMessages = [...(messages || [])].reverse();
|
|
14
16
|
const { getPrefixCls } = useProviderContext();
|
|
15
17
|
const prefixCls = getPrefixCls('chat-anywhere');
|
|
16
18
|
const uiConfig = useChatAnywhere(v => v.uiConfig);
|
|
17
19
|
const [ready, setReady] = useState(false);
|
|
18
20
|
const prevMessagesLengthRef = React.useRef(safeMessages.length);
|
|
21
|
+
const loadingMoreRef = React.useRef(false);
|
|
22
|
+
|
|
23
|
+
const handleLoadMoreStart = React.useCallback(() => {
|
|
24
|
+
loadingMoreRef.current = true;
|
|
25
|
+
}, []);
|
|
26
|
+
|
|
27
|
+
const handleLoadMoreEnd = React.useCallback(() => {
|
|
28
|
+
loadingMoreRef.current = false;
|
|
29
|
+
}, []);
|
|
30
|
+
|
|
31
|
+
const handleLoadMore = React.useCallback(async () => {
|
|
32
|
+
if (!onLoadMore) {
|
|
33
|
+
return { noMore: true };
|
|
34
|
+
}
|
|
35
|
+
const result = await onLoadMore();
|
|
36
|
+
const nextMessages = result?.messages || [];
|
|
37
|
+
|
|
38
|
+
if (nextMessages.length > 0) {
|
|
39
|
+
setMessages((prev) => {
|
|
40
|
+
const existedIds = new Set(prev.map((item) => item.id));
|
|
41
|
+
const mergedHistory = nextMessages
|
|
42
|
+
.filter((item) => !existedIds.has(item.id))
|
|
43
|
+
.map((item) => ({ ...item, history: true }));
|
|
44
|
+
return [...mergedHistory, ...prev];
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return { noMore: result?.noMore ?? true };
|
|
49
|
+
}, [onLoadMore, setMessages]);
|
|
19
50
|
|
|
20
51
|
React.useEffect(() => {
|
|
21
|
-
if (safeMessages.length > prevMessagesLengthRef.current) {
|
|
52
|
+
if (safeMessages.length > prevMessagesLengthRef.current && !loadingMoreRef.current) {
|
|
22
53
|
// New messages in desc mode should always bring viewport to latest bottom.
|
|
23
54
|
(ref as any)?.chatRef?.current?.scrollToBottom?.();
|
|
24
55
|
}
|
|
@@ -46,6 +77,9 @@ export default forwardRef(function (_, ref) {
|
|
|
46
77
|
pagination={uiConfig?.bubbleList?.pagination}
|
|
47
78
|
order="desc"
|
|
48
79
|
style={{ height: 0, flex: emptyMessage ? 0 : 1 }}
|
|
80
|
+
onLoadMore={handleLoadMore}
|
|
81
|
+
onLoadMoreStart={handleLoadMoreStart}
|
|
82
|
+
onLoadMoreEnd={handleLoadMoreEnd}
|
|
49
83
|
// @ts-ignore
|
|
50
84
|
ref={ref.chatRef}
|
|
51
85
|
items={safeMessages}
|
|
@@ -381,6 +381,7 @@ export default forwardRef(function (_, ref) {
|
|
|
381
381
|
sendDisabled={sendDisabled}
|
|
382
382
|
allowEmptySubmit={(onInput.allowEmptySubmit ?? true) && hasSubmittableFiles}
|
|
383
383
|
header={senderHeader}
|
|
384
|
+
footer={onInput.footer}
|
|
384
385
|
prefix={<>
|
|
385
386
|
{uploadPrefixNodes}
|
|
386
387
|
{onInput?.morePrefixActions}
|
|
@@ -206,6 +206,11 @@ export interface IChatAnywhereContext {
|
|
|
206
206
|
* @descriptionEn UI configuration object for customizing interface appearance and behavior
|
|
207
207
|
*/
|
|
208
208
|
uiConfig?: IChatAnywhereConfig['uiConfig'];
|
|
209
|
+
/**
|
|
210
|
+
* @description 加载更多消息的回调函数
|
|
211
|
+
* @descriptionEn Callback function for loading more messages
|
|
212
|
+
*/
|
|
213
|
+
onLoadMore?: IChatAnywhereConfig['onLoadMore'];
|
|
209
214
|
};
|
|
210
215
|
|
|
211
216
|
|
|
@@ -69,6 +69,11 @@ export interface TMessage {
|
|
|
69
69
|
* @descriptionEn Processing status of the message, affects display effects
|
|
70
70
|
*/
|
|
71
71
|
msgStatus?: 'finished' | 'interrupted' | 'generating' | 'error';
|
|
72
|
+
/**
|
|
73
|
+
* @description 是否为历史消息(通常由后端分页加载)
|
|
74
|
+
* @descriptionEn Whether this is a historical message (usually loaded by server-side pagination)
|
|
75
|
+
*/
|
|
76
|
+
history?: boolean;
|
|
72
77
|
}
|
|
73
78
|
|
|
74
79
|
export interface IChatAnywhereConfigUIConfig {
|
|
@@ -151,6 +156,11 @@ export interface IChatAnywhereConfigOnInput {
|
|
|
151
156
|
* @descriptionEn Input field header components
|
|
152
157
|
*/
|
|
153
158
|
header?: React.ReactElement | React.ReactElement[];
|
|
159
|
+
/**
|
|
160
|
+
* @description 输入框底部组件
|
|
161
|
+
* @descriptionEn Input field footer components
|
|
162
|
+
*/
|
|
163
|
+
footer?: React.ReactNode;
|
|
154
164
|
/**
|
|
155
165
|
* @description 是否启用用户focus时展开输入框组件
|
|
156
166
|
* @descriptionEn Whether to enable the user focus to expand the input box component
|
|
@@ -296,6 +306,14 @@ export interface IChatAnywhereConfig {
|
|
|
296
306
|
* @descriptionEn Configuration options for file upload functionality
|
|
297
307
|
*/
|
|
298
308
|
onUpload?: IChatAnywhereConfigOnUpload[];
|
|
309
|
+
/**
|
|
310
|
+
* @description 加载更多消息的回调函数
|
|
311
|
+
* @descriptionEn Callback function for loading more messages
|
|
312
|
+
*/
|
|
313
|
+
onLoadMore?(): Promise<{
|
|
314
|
+
messages: TMessage[];
|
|
315
|
+
noMore: boolean;
|
|
316
|
+
}>;
|
|
299
317
|
}
|
|
300
318
|
|
|
301
319
|
export interface IChatAnywhereRef extends IChatAnywhereContext {
|
|
@@ -185,6 +185,11 @@ export interface SenderProps extends Pick<TextareaProps, 'placeholder' | 'onKeyP
|
|
|
185
185
|
* @descriptionEn Header UI
|
|
186
186
|
*/
|
|
187
187
|
header?: React.ReactNode;
|
|
188
|
+
/**
|
|
189
|
+
* @description 底部 UI
|
|
190
|
+
* @descriptionEn Footer UI
|
|
191
|
+
*/
|
|
192
|
+
footer?: React.ReactNode;
|
|
188
193
|
/**
|
|
189
194
|
* @description 最大文本长度
|
|
190
195
|
* @descriptionEn Max content length
|
|
@@ -658,6 +663,7 @@ const ForwardSender = React.forwardRef<SenderRef, SenderProps>((props, ref) => {
|
|
|
658
663
|
</ActionButtonContext.Provider>
|
|
659
664
|
</div>
|
|
660
665
|
</div>
|
|
666
|
+
{props.footer}
|
|
661
667
|
</div>
|
|
662
668
|
</div>
|
|
663
669
|
</>
|
|
@@ -33,6 +33,11 @@ export interface BubbleListProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
33
33
|
};
|
|
34
34
|
pagination?: boolean;
|
|
35
35
|
order?: 'asc' | 'desc';
|
|
36
|
+
onLoadMore?: () => Promise<{
|
|
37
|
+
noMore: boolean;
|
|
38
|
+
}>;
|
|
39
|
+
onLoadMoreStart?: () => void;
|
|
40
|
+
onLoadMoreEnd?: () => void;
|
|
36
41
|
}
|
|
37
42
|
declare const ForwardBubbleList: React.ForwardRefExoticComponent<BubbleListProps & React.RefAttributes<BubbleListRef>>;
|
|
38
43
|
export default ForwardBubbleList;
|
package/lib/Bubble/BubbleList.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
2
2
|
var _excluded = ["key"];
|
|
3
|
+
function _regeneratorRuntime() { "use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = "function" == typeof Symbol ? Symbol : {}, a = i.iterator || "@@iterator", c = i.asyncIterator || "@@asyncIterator", u = i.toStringTag || "@@toStringTag"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, ""); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, "_invoke", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: "normal", arg: t.call(e, r) }; } catch (t) { return { type: "throw", arg: t }; } } e.wrap = wrap; var h = "suspendedStart", l = "suspendedYield", f = "executing", s = "completed", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { ["next", "throw", "return"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if ("throw" !== c.type) { var u = c.arg, h = u.value; return h && "object" == _typeof(h) && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) { invoke("next", t, i, a); }, function (t) { invoke("throw", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke("throw", t, i, a); }); } a(c.arg); } var r; o(this, "_invoke", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw new Error("Generator is already running"); if (o === s) { if ("throw" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else "return" === n.method && n.abrupt("return", n.arg); o = f; var p = tryCatch(e, r, n); if ("normal" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } "throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, "throw" === n && e.iterator.return && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y; var i = tryCatch(o, e.iterator, r.arg); if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = "normal", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: "root" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || "" === e) { var r = e[a]; if (r) return r.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + " is not iterable"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, "constructor", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) { var e = "function" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () { return this; }), define(g, "toString", function () { return "[object Generator]"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if ("throw" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if ("root" === i.tryLoc) return handle("end"); if (i.tryLoc <= this.prev) { var c = n.call(i, "catchLoc"), u = n.call(i, "finallyLoc"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw new Error("try statement without catch or finally"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) { var i = o; break; } } i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if ("throw" === t.type) throw t.arg; return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, catch: function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if ("throw" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw new Error("illegal catch attempt"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, "next" === this.method && (this.arg = t), y; } }, e; }
|
|
4
|
+
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
|
|
5
|
+
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
|
|
3
6
|
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
|
|
4
7
|
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
5
8
|
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
@@ -17,7 +20,7 @@ import Bubble from "./Bubble";
|
|
|
17
20
|
import ScrollToBottom from "./ScrollToBottom";
|
|
18
21
|
import Style from "./style/list";
|
|
19
22
|
import { useProviderContext } from "./..";
|
|
20
|
-
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
|
23
|
+
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
21
24
|
import cls from 'classnames';
|
|
22
25
|
import { useInViewport, usePrevious } from 'ahooks';
|
|
23
26
|
import { usePaginationItems } from "./hooks/usePaginationItemsData";
|
|
@@ -26,34 +29,42 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
26
29
|
import { createElement as _createElement } from "react";
|
|
27
30
|
import { Fragment as _Fragment } from "react/jsx-runtime";
|
|
28
31
|
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
29
|
-
function BubbleListContent(
|
|
30
|
-
var order =
|
|
31
|
-
paginationItems =
|
|
32
|
-
noMore =
|
|
33
|
-
loadMore =
|
|
34
|
-
scrollRef =
|
|
35
|
-
children =
|
|
32
|
+
function BubbleListContent(props) {
|
|
33
|
+
var order = props.order,
|
|
34
|
+
paginationItems = props.paginationItems,
|
|
35
|
+
noMore = props.noMore,
|
|
36
|
+
loadMore = props.loadMore,
|
|
37
|
+
scrollRef = props.scrollRef,
|
|
38
|
+
children = props.children,
|
|
39
|
+
onLoadMoreStart = props.onLoadMoreStart,
|
|
40
|
+
onLoadMoreEnd = props.onLoadMoreEnd;
|
|
36
41
|
var handleLoadMore = useCallback(function () {
|
|
37
42
|
return loadMore(scrollRef);
|
|
38
43
|
}, [loadMore, scrollRef]);
|
|
44
|
+
var moreUI = useMemo(function () {
|
|
45
|
+
if (noMore) return null;
|
|
46
|
+
return /*#__PURE__*/_jsx(LoadMore, {
|
|
47
|
+
handleLoadMore: handleLoadMore,
|
|
48
|
+
onLoadMoreStart: onLoadMoreStart,
|
|
49
|
+
onLoadMoreEnd: onLoadMoreEnd
|
|
50
|
+
});
|
|
51
|
+
}, [handleLoadMore, onLoadMoreStart, onLoadMoreEnd, noMore]);
|
|
39
52
|
return /*#__PURE__*/_jsxs(_Fragment, {
|
|
40
|
-
children: [order === 'asc' && !noMore ?
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
var key = _ref2.key,
|
|
44
|
-
bubble = _objectWithoutProperties(_ref2, _excluded);
|
|
53
|
+
children: [order === 'asc' && !noMore ? moreUI : null, children ? children : paginationItems.map(function (_ref, index) {
|
|
54
|
+
var key = _ref.key,
|
|
55
|
+
bubble = _objectWithoutProperties(_ref, _excluded);
|
|
45
56
|
var isLast = index === paginationItems.length - 1;
|
|
46
57
|
return /*#__PURE__*/_createElement(Bubble, _objectSpread(_objectSpread({}, bubble), {}, {
|
|
47
58
|
isLast: isLast,
|
|
48
59
|
key: bubble.id || key || index
|
|
49
60
|
}));
|
|
50
|
-
}), order === 'desc' && !noMore ?
|
|
51
|
-
handleLoadMore: handleLoadMore
|
|
52
|
-
}) : null]
|
|
61
|
+
}), order === 'desc' && !noMore ? moreUI : null]
|
|
53
62
|
});
|
|
54
63
|
}
|
|
55
|
-
function LoadMore(
|
|
56
|
-
var handleLoadMore =
|
|
64
|
+
function LoadMore(_ref2) {
|
|
65
|
+
var handleLoadMore = _ref2.handleLoadMore,
|
|
66
|
+
onLoadMoreStart = _ref2.onLoadMoreStart,
|
|
67
|
+
onLoadMoreEnd = _ref2.onLoadMoreEnd;
|
|
57
68
|
var ref = useRef(null);
|
|
58
69
|
var _useInViewport = useInViewport(ref),
|
|
59
70
|
_useInViewport2 = _slicedToArray(_useInViewport, 1),
|
|
@@ -70,12 +81,14 @@ function LoadMore(_ref3) {
|
|
|
70
81
|
if (inViewport && previousInViewport === undefined) return;
|
|
71
82
|
if (loading) return;
|
|
72
83
|
if (inViewport) {
|
|
84
|
+
onLoadMoreStart === null || onLoadMoreStart === void 0 || onLoadMoreStart();
|
|
73
85
|
setLoading(true);
|
|
74
86
|
handleLoadMore().finally(function () {
|
|
75
87
|
setLoading(false);
|
|
88
|
+
onLoadMoreEnd === null || onLoadMoreEnd === void 0 || onLoadMoreEnd();
|
|
76
89
|
});
|
|
77
90
|
}
|
|
78
|
-
}, [previousInViewport, inViewport, loading, handleLoadMore]);
|
|
91
|
+
}, [previousInViewport, inViewport, loading, handleLoadMore, onLoadMoreStart, onLoadMoreEnd]);
|
|
79
92
|
return /*#__PURE__*/_jsx("div", {
|
|
80
93
|
ref: ref,
|
|
81
94
|
className: "".concat(prefixCls, "-load-more"),
|
|
@@ -92,8 +105,12 @@ var BubbleList = function BubbleList(props, ref) {
|
|
|
92
105
|
order = _props$order === void 0 ? 'asc' : _props$order;
|
|
93
106
|
var _useState3 = useState(false),
|
|
94
107
|
_useState4 = _slicedToArray(_useState3, 2),
|
|
95
|
-
|
|
96
|
-
|
|
108
|
+
serverNoMore = _useState4[0],
|
|
109
|
+
setServerNoMore = _useState4[1];
|
|
110
|
+
var _useState5 = useState(false),
|
|
111
|
+
_useState6 = _slicedToArray(_useState5, 2),
|
|
112
|
+
showScrollToBottom = _useState6[0],
|
|
113
|
+
setShowScrollToBottom = _useState6[1];
|
|
97
114
|
var scrollRef = React.useRef(null);
|
|
98
115
|
var isAtBottomRef = React.useRef(true);
|
|
99
116
|
var _useProviderContext2 = useProviderContext(),
|
|
@@ -155,13 +172,62 @@ var BubbleList = function BubbleList(props, ref) {
|
|
|
155
172
|
})
|
|
156
173
|
};
|
|
157
174
|
}, [scrollToBottom]);
|
|
175
|
+
var enableServerPagination = Boolean(props.pagination && props.onLoadMore);
|
|
158
176
|
var _usePaginationItems = usePaginationItems(items, {
|
|
159
|
-
enable: props.pagination,
|
|
177
|
+
enable: Boolean(props.pagination && !enableServerPagination),
|
|
160
178
|
order: order
|
|
161
179
|
}),
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
180
|
+
localPaginationItems = _usePaginationItems.items,
|
|
181
|
+
localNoMore = _usePaginationItems.noMore,
|
|
182
|
+
localLoadMore = _usePaginationItems.loadMore;
|
|
183
|
+
var loadMoreFromServer = useCallback( /*#__PURE__*/function () {
|
|
184
|
+
var _ref3 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(innerScrollRef) {
|
|
185
|
+
var _scrollEl$scrollHeigh, _props$onLoadMore;
|
|
186
|
+
var scrollEl, prevScrollHeight, result, newScrollHeight;
|
|
187
|
+
return _regeneratorRuntime().wrap(function _callee$(_context) {
|
|
188
|
+
while (1) switch (_context.prev = _context.next) {
|
|
189
|
+
case 0:
|
|
190
|
+
scrollEl = innerScrollRef === null || innerScrollRef === void 0 ? void 0 : innerScrollRef.current;
|
|
191
|
+
prevScrollHeight = (_scrollEl$scrollHeigh = scrollEl === null || scrollEl === void 0 ? void 0 : scrollEl.scrollHeight) !== null && _scrollEl$scrollHeigh !== void 0 ? _scrollEl$scrollHeigh : 0;
|
|
192
|
+
_context.next = 4;
|
|
193
|
+
return (_props$onLoadMore = props.onLoadMore) === null || _props$onLoadMore === void 0 ? void 0 : _props$onLoadMore.call(props);
|
|
194
|
+
case 4:
|
|
195
|
+
result = _context.sent;
|
|
196
|
+
_context.next = 7;
|
|
197
|
+
return new Promise(function (resolve) {
|
|
198
|
+
return requestAnimationFrame(function () {
|
|
199
|
+
return resolve();
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
case 7:
|
|
203
|
+
if (scrollEl) {
|
|
204
|
+
newScrollHeight = scrollEl.scrollHeight;
|
|
205
|
+
scrollEl.scrollTop += newScrollHeight - prevScrollHeight;
|
|
206
|
+
}
|
|
207
|
+
setServerNoMore(Boolean(result === null || result === void 0 ? void 0 : result.noMore));
|
|
208
|
+
case 9:
|
|
209
|
+
case "end":
|
|
210
|
+
return _context.stop();
|
|
211
|
+
}
|
|
212
|
+
}, _callee);
|
|
213
|
+
}));
|
|
214
|
+
return function (_x) {
|
|
215
|
+
return _ref3.apply(this, arguments);
|
|
216
|
+
};
|
|
217
|
+
}(), [props.onLoadMore]);
|
|
218
|
+
var paginationItems = enableServerPagination ? items : localPaginationItems;
|
|
219
|
+
var noMore = enableServerPagination ? serverNoMore : localNoMore;
|
|
220
|
+
var loadMore = enableServerPagination ? loadMoreFromServer : localLoadMore;
|
|
221
|
+
useEffect(function () {
|
|
222
|
+
if (!enableServerPagination) return;
|
|
223
|
+
if (items.length === 0) {
|
|
224
|
+
setServerNoMore(false);
|
|
225
|
+
}
|
|
226
|
+
}, [enableServerPagination, items.length]);
|
|
227
|
+
useEffect(function () {
|
|
228
|
+
if (!enableServerPagination) return;
|
|
229
|
+
setServerNoMore(false);
|
|
230
|
+
}, [enableServerPagination, props.onLoadMore]);
|
|
165
231
|
useEffect(function () {
|
|
166
232
|
scrollToBottom('auto');
|
|
167
233
|
}, [items.length, scrollToBottom]);
|
|
@@ -193,6 +259,8 @@ var BubbleList = function BubbleList(props, ref) {
|
|
|
193
259
|
noMore: noMore,
|
|
194
260
|
loadMore: loadMore,
|
|
195
261
|
scrollRef: scrollRef,
|
|
262
|
+
onLoadMoreStart: props.onLoadMoreStart,
|
|
263
|
+
onLoadMoreEnd: props.onLoadMoreEnd,
|
|
196
264
|
children: props.children
|
|
197
265
|
})]
|
|
198
266
|
}), /*#__PURE__*/_jsx(ScrollToBottom, {
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
2
|
+
function _regeneratorRuntime() { "use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = "function" == typeof Symbol ? Symbol : {}, a = i.iterator || "@@iterator", c = i.asyncIterator || "@@asyncIterator", u = i.toStringTag || "@@toStringTag"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, ""); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, "_invoke", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: "normal", arg: t.call(e, r) }; } catch (t) { return { type: "throw", arg: t }; } } e.wrap = wrap; var h = "suspendedStart", l = "suspendedYield", f = "executing", s = "completed", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { ["next", "throw", "return"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if ("throw" !== c.type) { var u = c.arg, h = u.value; return h && "object" == _typeof(h) && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) { invoke("next", t, i, a); }, function (t) { invoke("throw", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke("throw", t, i, a); }); } a(c.arg); } var r; o(this, "_invoke", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw new Error("Generator is already running"); if (o === s) { if ("throw" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else "return" === n.method && n.abrupt("return", n.arg); o = f; var p = tryCatch(e, r, n); if ("normal" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } "throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, "throw" === n && e.iterator.return && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y; var i = tryCatch(o, e.iterator, r.arg); if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = "normal", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: "root" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || "" === e) { var r = e[a]; if (r) return r.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + " is not iterable"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, "constructor", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) { var e = "function" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () { return this; }), define(g, "toString", function () { return "[object Generator]"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if ("throw" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if ("root" === i.tryLoc) return handle("end"); if (i.tryLoc <= this.prev) { var c = n.call(i, "catchLoc"), u = n.call(i, "finallyLoc"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw new Error("try statement without catch or finally"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) { var i = o; break; } } i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if ("throw" === t.type) throw t.arg; return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, catch: function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if ("throw" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw new Error("illegal catch attempt"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, "next" === this.method && (this.arg = t), y; } }, e; }
|
|
3
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
4
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
2
5
|
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
3
6
|
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
|
|
4
7
|
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
8
|
+
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
|
|
9
|
+
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
|
|
5
10
|
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
|
|
6
11
|
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
7
12
|
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
|
|
@@ -29,6 +34,12 @@ export default /*#__PURE__*/forwardRef(function (_, ref) {
|
|
|
29
34
|
var messages = useChatAnywhere(function (v) {
|
|
30
35
|
return v.messages;
|
|
31
36
|
});
|
|
37
|
+
var setMessages = useChatAnywhere(function (v) {
|
|
38
|
+
return v.setMessages;
|
|
39
|
+
});
|
|
40
|
+
var onLoadMore = useChatAnywhere(function (v) {
|
|
41
|
+
return v.onLoadMore;
|
|
42
|
+
});
|
|
32
43
|
var safeMessages = _toConsumableArray(messages || []).reverse();
|
|
33
44
|
var _useProviderContext = useProviderContext(),
|
|
34
45
|
getPrefixCls = _useProviderContext.getPrefixCls;
|
|
@@ -41,8 +52,58 @@ export default /*#__PURE__*/forwardRef(function (_, ref) {
|
|
|
41
52
|
ready = _useState2[0],
|
|
42
53
|
setReady = _useState2[1];
|
|
43
54
|
var prevMessagesLengthRef = React.useRef(safeMessages.length);
|
|
55
|
+
var loadingMoreRef = React.useRef(false);
|
|
56
|
+
var handleLoadMoreStart = React.useCallback(function () {
|
|
57
|
+
loadingMoreRef.current = true;
|
|
58
|
+
}, []);
|
|
59
|
+
var handleLoadMoreEnd = React.useCallback(function () {
|
|
60
|
+
loadingMoreRef.current = false;
|
|
61
|
+
}, []);
|
|
62
|
+
var handleLoadMore = React.useCallback( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
|
|
63
|
+
var _result$noMore;
|
|
64
|
+
var result, nextMessages;
|
|
65
|
+
return _regeneratorRuntime().wrap(function _callee$(_context) {
|
|
66
|
+
while (1) switch (_context.prev = _context.next) {
|
|
67
|
+
case 0:
|
|
68
|
+
if (onLoadMore) {
|
|
69
|
+
_context.next = 2;
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
return _context.abrupt("return", {
|
|
73
|
+
noMore: true
|
|
74
|
+
});
|
|
75
|
+
case 2:
|
|
76
|
+
_context.next = 4;
|
|
77
|
+
return onLoadMore();
|
|
78
|
+
case 4:
|
|
79
|
+
result = _context.sent;
|
|
80
|
+
nextMessages = (result === null || result === void 0 ? void 0 : result.messages) || [];
|
|
81
|
+
if (nextMessages.length > 0) {
|
|
82
|
+
setMessages(function (prev) {
|
|
83
|
+
var existedIds = new Set(prev.map(function (item) {
|
|
84
|
+
return item.id;
|
|
85
|
+
}));
|
|
86
|
+
var mergedHistory = nextMessages.filter(function (item) {
|
|
87
|
+
return !existedIds.has(item.id);
|
|
88
|
+
}).map(function (item) {
|
|
89
|
+
return _objectSpread(_objectSpread({}, item), {}, {
|
|
90
|
+
history: true
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
return [].concat(_toConsumableArray(mergedHistory), _toConsumableArray(prev));
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
return _context.abrupt("return", {
|
|
97
|
+
noMore: (_result$noMore = result === null || result === void 0 ? void 0 : result.noMore) !== null && _result$noMore !== void 0 ? _result$noMore : true
|
|
98
|
+
});
|
|
99
|
+
case 8:
|
|
100
|
+
case "end":
|
|
101
|
+
return _context.stop();
|
|
102
|
+
}
|
|
103
|
+
}, _callee);
|
|
104
|
+
})), [onLoadMore, setMessages]);
|
|
44
105
|
React.useEffect(function () {
|
|
45
|
-
if (safeMessages.length > prevMessagesLengthRef.current) {
|
|
106
|
+
if (safeMessages.length > prevMessagesLengthRef.current && !loadingMoreRef.current) {
|
|
46
107
|
var _chatRef, _chatRef$scrollToBott;
|
|
47
108
|
// New messages in desc mode should always bring viewport to latest bottom.
|
|
48
109
|
ref === null || ref === void 0 || (_chatRef = ref.chatRef) === null || _chatRef === void 0 || (_chatRef = _chatRef.current) === null || _chatRef === void 0 || (_chatRef$scrollToBott = _chatRef.scrollToBottom) === null || _chatRef$scrollToBott === void 0 || _chatRef$scrollToBott.call(_chatRef);
|
|
@@ -63,7 +124,10 @@ export default /*#__PURE__*/forwardRef(function (_, ref) {
|
|
|
63
124
|
style: {
|
|
64
125
|
height: 0,
|
|
65
126
|
flex: emptyMessage ? 0 : 1
|
|
66
|
-
}
|
|
127
|
+
},
|
|
128
|
+
onLoadMore: handleLoadMore,
|
|
129
|
+
onLoadMoreStart: handleLoadMoreStart,
|
|
130
|
+
onLoadMoreEnd: handleLoadMoreEnd
|
|
67
131
|
// @ts-ignore
|
|
68
132
|
,
|
|
69
133
|
ref: ref.chatRef,
|
|
@@ -426,6 +426,7 @@ export default /*#__PURE__*/forwardRef(function (_, ref) {
|
|
|
426
426
|
sendDisabled: sendDisabled,
|
|
427
427
|
allowEmptySubmit: ((_onInput$allowEmptySu = onInput.allowEmptySubmit) !== null && _onInput$allowEmptySu !== void 0 ? _onInput$allowEmptySu : true) && hasSubmittableFiles,
|
|
428
428
|
header: senderHeader,
|
|
429
|
+
footer: onInput.footer,
|
|
429
430
|
prefix: /*#__PURE__*/_jsxs(_Fragment, {
|
|
430
431
|
children: [uploadPrefixNodes, onInput === null || onInput === void 0 ? void 0 : onInput.morePrefixActions]
|
|
431
432
|
}),
|
|
@@ -141,6 +141,11 @@ export interface IChatAnywhereContext {
|
|
|
141
141
|
* @descriptionEn UI configuration object for customizing interface appearance and behavior
|
|
142
142
|
*/
|
|
143
143
|
uiConfig?: IChatAnywhereConfig['uiConfig'];
|
|
144
|
+
/**
|
|
145
|
+
* @description 加载更多消息的回调函数
|
|
146
|
+
* @descriptionEn Callback function for loading more messages
|
|
147
|
+
*/
|
|
148
|
+
onLoadMore?: IChatAnywhereConfig['onLoadMore'];
|
|
144
149
|
}
|
|
145
150
|
export type ChatAnywhereRef = ReturnType<typeof useMessages> & ReturnType<typeof useInput> & ReturnType<typeof useSessionList> & {
|
|
146
151
|
setInputContent: (content: string, fileList?: UploadFile[][]) => void;
|
|
@@ -67,6 +67,11 @@ export interface TMessage {
|
|
|
67
67
|
* @descriptionEn Processing status of the message, affects display effects
|
|
68
68
|
*/
|
|
69
69
|
msgStatus?: 'finished' | 'interrupted' | 'generating' | 'error';
|
|
70
|
+
/**
|
|
71
|
+
* @description 是否为历史消息(通常由后端分页加载)
|
|
72
|
+
* @descriptionEn Whether this is a historical message (usually loaded by server-side pagination)
|
|
73
|
+
*/
|
|
74
|
+
history?: boolean;
|
|
70
75
|
}
|
|
71
76
|
export interface IChatAnywhereConfigUIConfig {
|
|
72
77
|
/**
|
|
@@ -147,6 +152,11 @@ export interface IChatAnywhereConfigOnInput {
|
|
|
147
152
|
* @descriptionEn Input field header components
|
|
148
153
|
*/
|
|
149
154
|
header?: React.ReactElement | React.ReactElement[];
|
|
155
|
+
/**
|
|
156
|
+
* @description 输入框底部组件
|
|
157
|
+
* @descriptionEn Input field footer components
|
|
158
|
+
*/
|
|
159
|
+
footer?: React.ReactNode;
|
|
150
160
|
/**
|
|
151
161
|
* @description 是否启用用户focus时展开输入框组件
|
|
152
162
|
* @descriptionEn Whether to enable the user focus to expand the input box component
|
|
@@ -294,6 +304,14 @@ export interface IChatAnywhereConfig {
|
|
|
294
304
|
* @descriptionEn Configuration options for file upload functionality
|
|
295
305
|
*/
|
|
296
306
|
onUpload?: IChatAnywhereConfigOnUpload[];
|
|
307
|
+
/**
|
|
308
|
+
* @description 加载更多消息的回调函数
|
|
309
|
+
* @descriptionEn Callback function for loading more messages
|
|
310
|
+
*/
|
|
311
|
+
onLoadMore?(): Promise<{
|
|
312
|
+
messages: TMessage[];
|
|
313
|
+
noMore: boolean;
|
|
314
|
+
}>;
|
|
297
315
|
}
|
|
298
316
|
export interface IChatAnywhereRef extends IChatAnywhereContext {
|
|
299
317
|
/**
|
package/lib/Sender/index.d.ts
CHANGED
|
@@ -147,6 +147,11 @@ export interface SenderProps extends Pick<TextareaProps, 'placeholder' | 'onKeyP
|
|
|
147
147
|
* @descriptionEn Header UI
|
|
148
148
|
*/
|
|
149
149
|
header?: React.ReactNode;
|
|
150
|
+
/**
|
|
151
|
+
* @description 底部 UI
|
|
152
|
+
* @descriptionEn Footer UI
|
|
153
|
+
*/
|
|
154
|
+
footer?: React.ReactNode;
|
|
150
155
|
/**
|
|
151
156
|
* @description 最大文本长度
|
|
152
157
|
* @descriptionEn Max content length
|
package/lib/Sender/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
# agentscope-runtime-starter-webui
|
|
2
|
-
|
|
3
|
-
## node version
|
|
4
|
-
|
|
5
|
-
> =22
|
|
6
|
-
|
|
7
|
-
## install
|
|
8
|
-
|
|
9
|
-
```
|
|
10
|
-
$ npm run install
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
## dev
|
|
14
|
-
|
|
15
|
-
```
|
|
16
|
-
$ npm run dev
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
## build
|
|
20
|
-
|
|
21
|
-
```
|
|
22
|
-
$ npm run build
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
## Core Code
|
|
26
|
-
```tsx
|
|
27
|
-
import { AgentScopeRuntimeWebUI } from '@agentscope-ai/chat';
|
|
28
|
-
|
|
29
|
-
const options = {
|
|
30
|
-
theme: {
|
|
31
|
-
colorPrimary: '#615CED',
|
|
32
|
-
darkMode: true,
|
|
33
|
-
prefix: 'agentscope-runtime-webui',
|
|
34
|
-
leftHeader: {
|
|
35
|
-
logo: 'https://img.alicdn.com/imgextra/i2/O1CN01lmoGYn1kjoXATy4PX_!!6000000004720-2-tps-200-200.png',
|
|
36
|
-
title: 'Runtime WebUI',
|
|
37
|
-
},
|
|
38
|
-
},
|
|
39
|
-
sender: {
|
|
40
|
-
maxLength: 10000,
|
|
41
|
-
disclaimer:
|
|
42
|
-
'AI can also make mistakes, so please check carefully and use it with caution',
|
|
43
|
-
},
|
|
44
|
-
|
|
45
|
-
welcome: {
|
|
46
|
-
greeting: 'Hello, how can I help you today?',
|
|
47
|
-
description:
|
|
48
|
-
'I am a helpful assistant that can help you with your questions.',
|
|
49
|
-
avatar:
|
|
50
|
-
'https://img.alicdn.com/imgextra/i2/O1CN01lmoGYn1kjoXATy4PX_!!6000000004720-2-tps-200-200.png',
|
|
51
|
-
prompts: [
|
|
52
|
-
{
|
|
53
|
-
value: 'Hello',
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
value: 'How are you?',
|
|
57
|
-
},
|
|
58
|
-
{
|
|
59
|
-
value: 'What can you do?',
|
|
60
|
-
},
|
|
61
|
-
],
|
|
62
|
-
},
|
|
63
|
-
api: {
|
|
64
|
-
baseURL: 'YOUR_API_URL',
|
|
65
|
-
token: 'YOUR_API_TOKEN', // is not required
|
|
66
|
-
},
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
<AgentScopeRuntimeWebUI
|
|
71
|
-
options={options}
|
|
72
|
-
/>
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
```
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import js from '@eslint/js'
|
|
2
|
-
import globals from 'globals'
|
|
3
|
-
import reactHooks from 'eslint-plugin-react-hooks'
|
|
4
|
-
import reactRefresh from 'eslint-plugin-react-refresh'
|
|
5
|
-
import tseslint from 'typescript-eslint'
|
|
6
|
-
|
|
7
|
-
export default tseslint.config(
|
|
8
|
-
{ ignores: ['dist'] },
|
|
9
|
-
{
|
|
10
|
-
extends: [js.configs.recommended, ...tseslint.configs.recommended],
|
|
11
|
-
files: ['**/*.{ts,tsx}'],
|
|
12
|
-
languageOptions: {
|
|
13
|
-
ecmaVersion: 2020,
|
|
14
|
-
globals: globals.browser,
|
|
15
|
-
},
|
|
16
|
-
plugins: {
|
|
17
|
-
'react-hooks': reactHooks,
|
|
18
|
-
'react-refresh': reactRefresh,
|
|
19
|
-
},
|
|
20
|
-
rules: {
|
|
21
|
-
...reactHooks.configs.recommended.rules,
|
|
22
|
-
'react-refresh/only-export-components': [
|
|
23
|
-
'warn',
|
|
24
|
-
{ allowConstantExport: true },
|
|
25
|
-
],
|
|
26
|
-
},
|
|
27
|
-
},
|
|
28
|
-
)
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8" />
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
-
<title>AgentScope Runtime Starter WebUI</title>
|
|
7
|
-
</head>
|
|
8
|
-
<body>
|
|
9
|
-
<div id="root"></div>
|
|
10
|
-
<script type="module" src="/src/main.tsx"></script>
|
|
11
|
-
</body>
|
|
12
|
-
</html>
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "agentscope-runtime-starter-webui",
|
|
3
|
-
"private": true,
|
|
4
|
-
"version": "0.0.0",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"scripts": {
|
|
7
|
-
"dev": "vite --host",
|
|
8
|
-
"build": "tsc -b && vite build",
|
|
9
|
-
"lint": "eslint .",
|
|
10
|
-
"preview": "vite preview"
|
|
11
|
-
},
|
|
12
|
-
"dependencies": {
|
|
13
|
-
"@agentscope-ai/icons": "^1.0.46",
|
|
14
|
-
"@agentscope-ai/chat": "1.1.59-beta.1775119922876",
|
|
15
|
-
"@agentscope-ai/design": "^1.0.19",
|
|
16
|
-
"antd": "^5.29.1",
|
|
17
|
-
"antd-style": "^3.7.1",
|
|
18
|
-
"react": "^18",
|
|
19
|
-
"react-dom": "^18"
|
|
20
|
-
},
|
|
21
|
-
"devDependencies": {
|
|
22
|
-
"@eslint/js": "^9.25.0",
|
|
23
|
-
"@types/react": "^18",
|
|
24
|
-
"@types/react-dom": "^18",
|
|
25
|
-
"@vitejs/plugin-react": "^4.4.1",
|
|
26
|
-
"eslint": "^9.25.0",
|
|
27
|
-
"eslint-plugin-react-hooks": "^5.2.0",
|
|
28
|
-
"eslint-plugin-react-refresh": "^0.4.19",
|
|
29
|
-
"globals": "^16.0.0",
|
|
30
|
-
"typescript": "~5.8.3",
|
|
31
|
-
"typescript-eslint": "^8.30.1",
|
|
32
|
-
"vite": "^6.3.5"
|
|
33
|
-
}
|
|
34
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import Chat from './components/Chat';
|
|
2
|
-
|
|
3
|
-
import { createGlobalStyle } from 'antd-style';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const GlobalStyle = createGlobalStyle`
|
|
7
|
-
* {
|
|
8
|
-
margin: 0;
|
|
9
|
-
box-sizing: border-box;
|
|
10
|
-
}
|
|
11
|
-
`;
|
|
12
|
-
|
|
13
|
-
function App() {
|
|
14
|
-
return <>
|
|
15
|
-
<GlobalStyle />
|
|
16
|
-
<Chat />
|
|
17
|
-
</>
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export default App
|
package/components/AgentScopeRuntimeWebUI/bailian-high-code-webui/src/components/Cards/Weather.tsx
DELETED
|
@@ -1,234 +0,0 @@
|
|
|
1
|
-
import { createStyles } from 'antd-style';
|
|
2
|
-
|
|
3
|
-
interface IToolContentItem {
|
|
4
|
-
type: string;
|
|
5
|
-
object?: string;
|
|
6
|
-
status: string;
|
|
7
|
-
delta?: boolean | null;
|
|
8
|
-
msg_id?: string;
|
|
9
|
-
index?: number;
|
|
10
|
-
error?: unknown;
|
|
11
|
-
sequence_number?: number | null;
|
|
12
|
-
data: {
|
|
13
|
-
name: string;
|
|
14
|
-
arguments?: string;
|
|
15
|
-
output?: string;
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
interface IToolMessage {
|
|
20
|
-
id: string;
|
|
21
|
-
object?: string;
|
|
22
|
-
type: string;
|
|
23
|
-
role: string;
|
|
24
|
-
status: string;
|
|
25
|
-
content: IToolContentItem[];
|
|
26
|
-
code?: string | null;
|
|
27
|
-
message?: string | null;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export interface IWeatherItem {
|
|
31
|
-
location: string;
|
|
32
|
-
weather: string;
|
|
33
|
-
temperature: number;
|
|
34
|
-
date: string;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function parseOutput(data: IToolMessage): IWeatherItem[] {
|
|
38
|
-
const outputContent = data.content[1]?.data;
|
|
39
|
-
try {
|
|
40
|
-
// @ts-ignore
|
|
41
|
-
return JSON.parse(JSON.parse(outputContent.output));
|
|
42
|
-
} catch {
|
|
43
|
-
return [];
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const weatherIcons: Record<string, string> = {
|
|
48
|
-
sunny: '☀️',
|
|
49
|
-
cloudy: '☁️',
|
|
50
|
-
rainy: '🌧️',
|
|
51
|
-
snowy: '❄️',
|
|
52
|
-
stormy: '⛈️',
|
|
53
|
-
windy: '💨',
|
|
54
|
-
foggy: '🌫️',
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
const weatherLabels: Record<string, string> = {
|
|
58
|
-
sunny: '晴',
|
|
59
|
-
cloudy: '多云',
|
|
60
|
-
rainy: '雨',
|
|
61
|
-
snowy: '雪',
|
|
62
|
-
stormy: '暴风雨',
|
|
63
|
-
windy: '大风',
|
|
64
|
-
foggy: '雾',
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
function formatDate(dateStr: string) {
|
|
68
|
-
const d = new Date(dateStr);
|
|
69
|
-
const weekdays = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
|
|
70
|
-
const month = d.getMonth() + 1;
|
|
71
|
-
const day = d.getDate();
|
|
72
|
-
const today = new Date();
|
|
73
|
-
const isToday =
|
|
74
|
-
d.getFullYear() === today.getFullYear() &&
|
|
75
|
-
d.getMonth() === today.getMonth() &&
|
|
76
|
-
d.getDate() === today.getDate();
|
|
77
|
-
return {
|
|
78
|
-
weekday: isToday ? '今天' : weekdays[d.getDay()],
|
|
79
|
-
date: `${month}/${day}`,
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
const useStyles = createStyles(({ token, css }) => ({
|
|
84
|
-
wrapper: css`
|
|
85
|
-
border-radius: 12px;
|
|
86
|
-
border: 1px solid ${token.colorBorderSecondary};
|
|
87
|
-
background: ${token.colorBgElevated};
|
|
88
|
-
overflow: hidden;
|
|
89
|
-
`,
|
|
90
|
-
header: css`
|
|
91
|
-
display: flex;
|
|
92
|
-
align-items: center;
|
|
93
|
-
justify-content: space-between;
|
|
94
|
-
padding: 14px 16px;
|
|
95
|
-
border-bottom: 1px solid ${token.colorBorderSecondary};
|
|
96
|
-
`,
|
|
97
|
-
locationRow: css`
|
|
98
|
-
display: flex;
|
|
99
|
-
align-items: center;
|
|
100
|
-
gap: 6px;
|
|
101
|
-
`,
|
|
102
|
-
locationIcon: css`
|
|
103
|
-
font-size: 16px;
|
|
104
|
-
line-height: 1;
|
|
105
|
-
`,
|
|
106
|
-
locationText: css`
|
|
107
|
-
font-size: 14px;
|
|
108
|
-
font-weight: 600;
|
|
109
|
-
color: ${token.colorText};
|
|
110
|
-
`,
|
|
111
|
-
todayTemp: css`
|
|
112
|
-
font-size: 22px;
|
|
113
|
-
font-weight: 700;
|
|
114
|
-
color: ${token.colorText};
|
|
115
|
-
display: flex;
|
|
116
|
-
align-items: center;
|
|
117
|
-
gap: 6px;
|
|
118
|
-
`,
|
|
119
|
-
todayWeather: css`
|
|
120
|
-
font-size: 13px;
|
|
121
|
-
font-weight: 400;
|
|
122
|
-
color: ${token.colorTextSecondary};
|
|
123
|
-
`,
|
|
124
|
-
container: css`
|
|
125
|
-
display: flex;
|
|
126
|
-
overflow-x: auto;
|
|
127
|
-
padding: 14px 12px;
|
|
128
|
-
`,
|
|
129
|
-
card: css`
|
|
130
|
-
flex: 1;
|
|
131
|
-
flex-shrink: 0;
|
|
132
|
-
display: flex;
|
|
133
|
-
flex-direction: column;
|
|
134
|
-
align-items: center;
|
|
135
|
-
gap: 8px;
|
|
136
|
-
padding: 10px 12px;
|
|
137
|
-
border-radius: 10px;
|
|
138
|
-
min-width: 72px;
|
|
139
|
-
transition: background 0.2s;
|
|
140
|
-
cursor: default;
|
|
141
|
-
&:hover {
|
|
142
|
-
background: ${token.colorFillQuaternary};
|
|
143
|
-
}
|
|
144
|
-
`,
|
|
145
|
-
todayCard: css`
|
|
146
|
-
background: ${token.colorPrimaryBg};
|
|
147
|
-
&:hover {
|
|
148
|
-
background: ${token.colorPrimaryBgHover};
|
|
149
|
-
}
|
|
150
|
-
`,
|
|
151
|
-
weekday: css`
|
|
152
|
-
font-size: 12px;
|
|
153
|
-
font-weight: 500;
|
|
154
|
-
color: ${token.colorTextSecondary};
|
|
155
|
-
line-height: 1;
|
|
156
|
-
`,
|
|
157
|
-
todayWeekday: css`
|
|
158
|
-
color: ${token.colorPrimary};
|
|
159
|
-
font-weight: 600;
|
|
160
|
-
`,
|
|
161
|
-
date: css`
|
|
162
|
-
font-size: 11px;
|
|
163
|
-
color: ${token.colorTextQuaternary};
|
|
164
|
-
line-height: 1;
|
|
165
|
-
`,
|
|
166
|
-
icon: css`
|
|
167
|
-
font-size: 26px;
|
|
168
|
-
line-height: 1;
|
|
169
|
-
`,
|
|
170
|
-
temp: css`
|
|
171
|
-
font-size: 15px;
|
|
172
|
-
font-weight: 600;
|
|
173
|
-
color: ${token.colorText};
|
|
174
|
-
line-height: 1;
|
|
175
|
-
`,
|
|
176
|
-
label: css`
|
|
177
|
-
font-size: 11px;
|
|
178
|
-
color: ${token.colorTextTertiary};
|
|
179
|
-
line-height: 1;
|
|
180
|
-
`,
|
|
181
|
-
}));
|
|
182
|
-
|
|
183
|
-
export default function Weather(props: { data: IToolMessage }) {
|
|
184
|
-
const items = parseOutput(props.data);
|
|
185
|
-
const { styles, cx } = useStyles();
|
|
186
|
-
|
|
187
|
-
if (!items.length) return null;
|
|
188
|
-
|
|
189
|
-
const todayItem = items.find((_, i) => {
|
|
190
|
-
const { weekday } = formatDate(items[i].date);
|
|
191
|
-
return weekday === '今天';
|
|
192
|
-
}) || items[0];
|
|
193
|
-
|
|
194
|
-
return (
|
|
195
|
-
<div className={styles.wrapper}>
|
|
196
|
-
<div className={styles.header}>
|
|
197
|
-
<div className={styles.locationRow}>
|
|
198
|
-
<span className={styles.locationIcon}>📍</span>
|
|
199
|
-
<span className={styles.locationText}>{items[0].location}</span>
|
|
200
|
-
</div>
|
|
201
|
-
<div className={styles.todayTemp}>
|
|
202
|
-
{weatherIcons[todayItem.weather] || '🌤️'} {todayItem.temperature}°
|
|
203
|
-
<span className={styles.todayWeather}>
|
|
204
|
-
{weatherLabels[todayItem.weather] || todayItem.weather}
|
|
205
|
-
</span>
|
|
206
|
-
</div>
|
|
207
|
-
</div>
|
|
208
|
-
<div className={styles.container}>
|
|
209
|
-
{items.map((item) => {
|
|
210
|
-
const { weekday, date } = formatDate(item.date);
|
|
211
|
-
const isToday = weekday === '今天';
|
|
212
|
-
return (
|
|
213
|
-
<div
|
|
214
|
-
key={item.date}
|
|
215
|
-
className={cx(styles.card, isToday && styles.todayCard)}
|
|
216
|
-
>
|
|
217
|
-
<span className={cx(styles.weekday, isToday && styles.todayWeekday)}>
|
|
218
|
-
{weekday}
|
|
219
|
-
</span>
|
|
220
|
-
<span className={styles.date}>{date}</span>
|
|
221
|
-
<span className={styles.icon}>
|
|
222
|
-
{weatherIcons[item.weather] || '🌤️'}
|
|
223
|
-
</span>
|
|
224
|
-
<span className={styles.temp}>{item.temperature}°</span>
|
|
225
|
-
<span className={styles.label}>
|
|
226
|
-
{weatherLabels[item.weather] || item.weather}
|
|
227
|
-
</span>
|
|
228
|
-
</div>
|
|
229
|
-
);
|
|
230
|
-
})}
|
|
231
|
-
</div>
|
|
232
|
-
</div>
|
|
233
|
-
);
|
|
234
|
-
}
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { IAgentScopeRuntimeWebUIOptions } from '@agentscope-ai/chat';
|
|
2
|
-
import Weather from '../Cards/Weather';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const config: IAgentScopeRuntimeWebUIOptions = {
|
|
6
|
-
customToolRenderConfig: {
|
|
7
|
-
'weather search mock': Weather,
|
|
8
|
-
},
|
|
9
|
-
theme: {
|
|
10
|
-
colorPrimary: '#615CED',
|
|
11
|
-
darkMode: true,
|
|
12
|
-
prefix: 'agentscope-runtime-webui',
|
|
13
|
-
leftHeader: {
|
|
14
|
-
logo: 'https://img.alicdn.com/imgextra/i2/O1CN01lmoGYn1kjoXATy4PX_!!6000000004720-2-tps-200-200.png',
|
|
15
|
-
title: 'Runtime WebUI',
|
|
16
|
-
},
|
|
17
|
-
},
|
|
18
|
-
sender: {
|
|
19
|
-
maxLength: 10000,
|
|
20
|
-
disclaimer:
|
|
21
|
-
'AI can also make mistakes, so please check carefully and use it with caution',
|
|
22
|
-
},
|
|
23
|
-
session: {
|
|
24
|
-
multiple: false,
|
|
25
|
-
},
|
|
26
|
-
|
|
27
|
-
welcome: {
|
|
28
|
-
greeting: 'Hello, how can I help you today?',
|
|
29
|
-
description:
|
|
30
|
-
'I am a helpful assistant that can help you with your questions.',
|
|
31
|
-
avatar:
|
|
32
|
-
'https://img.alicdn.com/imgextra/i2/O1CN01lmoGYn1kjoXATy4PX_!!6000000004720-2-tps-200-200.png',
|
|
33
|
-
prompts: [
|
|
34
|
-
{
|
|
35
|
-
value: 'Hello',
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
value: 'How are you?',
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
value: 'What can you do?',
|
|
42
|
-
},
|
|
43
|
-
],
|
|
44
|
-
},
|
|
45
|
-
api: {
|
|
46
|
-
baseURL: 'https://highcodnvvwbdks-ptzchpamaz.cn-beijing.fcapp.run/process',
|
|
47
|
-
token: '32a3e4da-528a-462d-a270-74b10cb21d75',
|
|
48
|
-
enableHistoryMessages: true,
|
|
49
|
-
},
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
export default config
|
package/components/AgentScopeRuntimeWebUI/bailian-high-code-webui/src/components/Chat/index.tsx
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { AgentScopeRuntimeWebUI, IAgentScopeRuntimeWebUIOptions } from '@agentscope-ai/chat';
|
|
2
|
-
import defaultConfig from './defaultConfig';
|
|
3
|
-
|
|
4
|
-
export default function () {
|
|
5
|
-
|
|
6
|
-
return <div style={{ height: '100vh' }}>
|
|
7
|
-
<AgentScopeRuntimeWebUI
|
|
8
|
-
options={defaultConfig as unknown as IAgentScopeRuntimeWebUIOptions}
|
|
9
|
-
/>
|
|
10
|
-
</div>;
|
|
11
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
|
4
|
-
"target": "ES2020",
|
|
5
|
-
"useDefineForClassFields": true,
|
|
6
|
-
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
|
7
|
-
"module": "ESNext",
|
|
8
|
-
"skipLibCheck": true,
|
|
9
|
-
|
|
10
|
-
"moduleResolution": "bundler",
|
|
11
|
-
"allowImportingTsExtensions": true,
|
|
12
|
-
"moduleDetection": "force",
|
|
13
|
-
"noEmit": true,
|
|
14
|
-
"jsx": "react-jsx",
|
|
15
|
-
|
|
16
|
-
"strict": true,
|
|
17
|
-
"noUnusedLocals": true,
|
|
18
|
-
"noUnusedParameters": true,
|
|
19
|
-
"erasableSyntaxOnly": true,
|
|
20
|
-
"noFallthroughCasesInSwitch": true,
|
|
21
|
-
"noUncheckedSideEffectImports": true
|
|
22
|
-
},
|
|
23
|
-
"include": ["src"]
|
|
24
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
|
|
4
|
-
"target": "ES2022",
|
|
5
|
-
"lib": ["ES2023"],
|
|
6
|
-
"module": "ESNext",
|
|
7
|
-
"skipLibCheck": true,
|
|
8
|
-
|
|
9
|
-
"moduleResolution": "bundler",
|
|
10
|
-
"allowImportingTsExtensions": true,
|
|
11
|
-
"moduleDetection": "force",
|
|
12
|
-
"noEmit": true,
|
|
13
|
-
|
|
14
|
-
"strict": true,
|
|
15
|
-
"noUnusedLocals": true,
|
|
16
|
-
"noUnusedParameters": true,
|
|
17
|
-
"erasableSyntaxOnly": true,
|
|
18
|
-
"noFallthroughCasesInSwitch": true,
|
|
19
|
-
"noUncheckedSideEffectImports": true
|
|
20
|
-
},
|
|
21
|
-
"include": ["vite.config.ts"]
|
|
22
|
-
}
|