@ai-group/chat-sdk 3.5.3 → 3.5.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/dist/cjs/components/XAdkChatbot/index.js +18 -0
  2. package/dist/cjs/components/XAdkChatbot/index.js.map +2 -2
  3. package/dist/cjs/components/XAdkProvider/compound/DefaultLayout.js +10 -13
  4. package/dist/cjs/components/XAdkProvider/compound/DefaultLayout.js.map +2 -2
  5. package/dist/cjs/components/XAdkProvider/compound/styles.d.ts +0 -1
  6. package/dist/cjs/components/XAdkProvider/compound/styles.js +0 -10
  7. package/dist/cjs/components/XAdkProvider/compound/styles.js.map +2 -2
  8. package/dist/cjs/components/XAdkSender/index.js +2 -1
  9. package/dist/cjs/components/XAdkSender/index.js.map +2 -2
  10. package/dist/cjs/components/XAdkSender/styles.js +18 -1
  11. package/dist/cjs/components/XAdkSender/styles.js.map +2 -2
  12. package/dist/cjs/components/XAiChatbot/index.d.ts +1 -1
  13. package/dist/cjs/components/XAiChatbot/index.js +183 -50
  14. package/dist/cjs/components/XAiChatbot/index.js.map +2 -2
  15. package/dist/cjs/types/XAdkSender.d.ts +2 -0
  16. package/dist/cjs/types/XAdkSender.js.map +1 -1
  17. package/dist/esm/components/XAdkChatbot/index.js +22 -0
  18. package/dist/esm/components/XAdkChatbot/index.js.map +1 -1
  19. package/dist/esm/components/XAdkProvider/compound/DefaultLayout.js +3 -5
  20. package/dist/esm/components/XAdkProvider/compound/DefaultLayout.js.map +1 -1
  21. package/dist/esm/components/XAdkProvider/compound/styles.d.ts +0 -1
  22. package/dist/esm/components/XAdkProvider/compound/styles.js +2 -3
  23. package/dist/esm/components/XAdkProvider/compound/styles.js.map +1 -1
  24. package/dist/esm/components/XAdkSender/index.js +3 -1
  25. package/dist/esm/components/XAdkSender/index.js.map +1 -1
  26. package/dist/esm/components/XAdkSender/styles.js +2 -2
  27. package/dist/esm/components/XAdkSender/styles.js.map +1 -1
  28. package/dist/esm/components/XAiChatbot/index.d.ts +1 -1
  29. package/dist/esm/components/XAiChatbot/index.js +56 -56
  30. package/dist/esm/components/XAiChatbot/index.js.map +1 -1
  31. package/dist/esm/types/XAdkSender.d.ts +2 -0
  32. package/dist/esm/types/XAdkSender.js.map +1 -1
  33. package/dist/umd/chat-sdk.min.js +1 -1
  34. package/package.json +1 -1
@@ -76,7 +76,10 @@ md.renderer.rules.link_open = (tokens, idx, options, env, self) => {
76
76
  }
77
77
  return defaultRender(tokens, idx, options, env, self);
78
78
  };
79
- var ActionHeader = ({ execute = [], thinks = "" }) => {
79
+ var ActionHeader = ({
80
+ execute = [],
81
+ thinks = ""
82
+ }) => {
80
83
  var _a;
81
84
  const styles = (0, import_styles.useStyles)();
82
85
  const [expanded, setExpanded] = (0, import_react.useState)(true);
@@ -87,39 +90,109 @@ var ActionHeader = ({ execute = [], thinks = "" }) => {
87
90
  const { name } = last;
88
91
  const icon = (last == null ? void 0 : last.icon) || ((_a = last == null ? void 0 : last.extra) == null ? void 0 : _a.icon);
89
92
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: styles.actionHeaderWrapper, children: [
90
- !expanded && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: styles.actionTitle, onClick: () => setExpanded((v) => !v), children: [
91
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src: import_think.default, alt: "icon", className: styles.actionHeaderIcon }),
92
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: styles.flex1, children: "运行过程" }),
93
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { alt: "展开icon", src: import_arrow_down.default, className: styles.w("16px") })
94
- ] }),
93
+ !expanded && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
94
+ "div",
95
+ {
96
+ className: styles.actionTitle,
97
+ onClick: () => setExpanded((v) => !v),
98
+ children: [
99
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src: import_think.default, alt: "icon", className: styles.actionHeaderIcon }),
100
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: styles.flex1, children: "运行过程" }),
101
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { alt: "展开icon", src: import_arrow_down.default, className: styles.w("16px") })
102
+ ]
103
+ }
104
+ ),
95
105
  expanded && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: styles.actionHeaderDetail, children: [
96
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: styles.actionDetailTitle, onClick: () => setExpanded((v) => !v), children: [
97
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src: import_think.default, alt: "", className: (0, import_clsx.default)(styles.w(14)) }),
98
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: (0, import_clsx.default)(styles.flex1, styles.pl(10)), children: "隐藏运行过程" }),
99
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { alt: "收起icon", src: import_arrow_up.default, className: styles.w("16px") })
100
- ] }),
101
- thinks && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: styles.actionDetailContent, style: { whiteSpace: "pre-line" }, children: thinks }),
106
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
107
+ "div",
108
+ {
109
+ className: styles.actionDetailTitle,
110
+ onClick: () => setExpanded((v) => !v),
111
+ children: [
112
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src: import_think.default, alt: "", className: (0, import_clsx.default)(styles.w(14)) }),
113
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: (0, import_clsx.default)(styles.flex1, styles.pl(10)), children: "隐藏运行过程" }),
114
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { alt: "收起icon", src: import_arrow_up.default, className: styles.w("16px") })
115
+ ]
116
+ }
117
+ ),
118
+ thinks && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
119
+ "div",
120
+ {
121
+ className: styles.actionDetailContent,
122
+ style: { whiteSpace: "pre-line" },
123
+ children: thinks
124
+ }
125
+ ),
102
126
  execute && execute.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
103
- !executeExpanded && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: styles.executeHiddenWrapper, onClick: () => setExecuteExpanded((v) => !v), children: [
104
- icon && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src: icon, alt: "icon", className: styles.h(15) }),
105
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: styles.flex1, children: name }),
106
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { alt: "工具icon", src: import_arrow_down_blue.default, className: styles.w("16px") })
107
- ] }),
127
+ !executeExpanded && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
128
+ "div",
129
+ {
130
+ className: styles.executeHiddenWrapper,
131
+ onClick: () => setExecuteExpanded((v) => !v),
132
+ children: [
133
+ icon && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src: icon, alt: "icon", className: styles.h(15) }),
134
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: styles.flex1, children: name }),
135
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
136
+ "img",
137
+ {
138
+ alt: "工具icon",
139
+ src: import_arrow_down_blue.default,
140
+ className: styles.w("16px")
141
+ }
142
+ )
143
+ ]
144
+ }
145
+ ),
108
146
  executeExpanded && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: styles.executeWrapper, children: [
109
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: styles.executeTitle, onClick: () => setExecuteExpanded((v) => !v), children: [
110
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src: import_group.default, alt: "icon", className: styles.executeHeaderIcon }),
111
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: styles.flex1, children: "隐藏运行详情" }),
112
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { alt: "展开详情icon", src: import_arrow_up.default, className: styles.w("16px") })
113
- ] }),
147
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
148
+ "div",
149
+ {
150
+ className: styles.executeTitle,
151
+ onClick: () => setExecuteExpanded((v) => !v),
152
+ children: [
153
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
154
+ "img",
155
+ {
156
+ src: import_group.default,
157
+ alt: "icon",
158
+ className: styles.executeHeaderIcon
159
+ }
160
+ ),
161
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: styles.flex1, children: "隐藏运行详情" }),
162
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
163
+ "img",
164
+ {
165
+ alt: "展开详情icon",
166
+ src: import_arrow_up.default,
167
+ className: styles.w("16px")
168
+ }
169
+ )
170
+ ]
171
+ }
172
+ ),
114
173
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: styles.executeContent, children: execute.map((action, idx) => {
115
174
  var _a2, _b, _c;
116
175
  const thinkIcon2 = (action == null ? void 0 : action.expandIcon) || ((_a2 = action == null ? void 0 : action.extra) == null ? void 0 : _a2.expandIcon) || ((_b = action == null ? void 0 : action.extra) == null ? void 0 : _b.icon) || (action == null ? void 0 : action.icon);
117
176
  const thinkCost = (action == null ? void 0 : action.cost) || ((_c = action == null ? void 0 : action.extra) == null ? void 0 : _c.cost);
118
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: styles.actionHeaderDetailItem, children: [
119
- thinkIcon2 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src: thinkIcon2, alt: "icon", className: styles.actionHeaderIcon }),
120
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: action == null ? void 0 : action.name }),
121
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: styles.actionHeaderCost, children: thinkCost ? `${thinkCost}s` : "" })
122
- ] }, action.uniqueId || idx);
177
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
178
+ "div",
179
+ {
180
+ className: styles.actionHeaderDetailItem,
181
+ children: [
182
+ thinkIcon2 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
183
+ "img",
184
+ {
185
+ src: thinkIcon2,
186
+ alt: "icon",
187
+ className: styles.actionHeaderIcon
188
+ }
189
+ ),
190
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: action == null ? void 0 : action.name }),
191
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: styles.actionHeaderCost, children: thinkCost ? `${thinkCost}s` : "" })
192
+ ]
193
+ },
194
+ action.uniqueId || idx
195
+ );
123
196
  }) })
124
197
  ] })
125
198
  ] })
@@ -196,16 +269,29 @@ var XAiChatbot = (props) => {
196
269
  isScriptScrolling.current = false;
197
270
  }, 0);
198
271
  };
199
- const FooterActions = ({ data, lastMessage = false }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: (0, import_clsx.default)(styles.flex, styles.gap(13)), children: messageActions.map((action, index) => {
272
+ const FooterActions = ({
273
+ data,
274
+ lastMessage = false
275
+ }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: (0, import_clsx.default)(styles.flex, styles.gap(13)), children: messageActions.map((action, index) => {
200
276
  var _a;
201
277
  if (!lastMessage && action.key === "redo")
202
278
  return null;
203
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_antd.Tooltip, { title: action.tooltip, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: styles.cursor("pointer"), onClick: () => onMessagesActionsCallback == null ? void 0 : onMessagesActionsCallback(index, data), children: [
204
- action.icon,
205
- (_a = action.render) == null ? void 0 : _a.call(action, index, data)
206
- ] }) }, action.key);
279
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_antd.Tooltip, { title: action.tooltip, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
280
+ "span",
281
+ {
282
+ className: styles.cursor("pointer"),
283
+ onClick: () => onMessagesActionsCallback == null ? void 0 : onMessagesActionsCallback(index, data),
284
+ children: [
285
+ action.icon,
286
+ (_a = action.render) == null ? void 0 : _a.call(action, index, data)
287
+ ]
288
+ }
289
+ ) }, action.key);
207
290
  }) });
208
- const MessageFooter = ({ data, lastMessage = false }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
291
+ const MessageFooter = ({
292
+ data,
293
+ lastMessage = false
294
+ }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
209
295
  messageTooltip == null ? void 0 : messageTooltip(data),
210
296
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FooterActions, { data, lastMessage })
211
297
  ] });
@@ -213,7 +299,12 @@ var XAiChatbot = (props) => {
213
299
  assistant: {
214
300
  placement: "start",
215
301
  avatar: () => {
216
- return avatar || /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons.UserOutlined, { className: (0, import_clsx.default)(styles.bg("#fde3cf"), styles.userAvatar) });
302
+ return avatar || /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
303
+ import_icons.UserOutlined,
304
+ {
305
+ className: (0, import_clsx.default)(styles.bg("#fde3cf"), styles.userAvatar)
306
+ }
307
+ );
217
308
  },
218
309
  typing: { step: 5, interval: 20, effect: "typing" },
219
310
  style: {
@@ -226,7 +317,12 @@ var XAiChatbot = (props) => {
226
317
  user: {
227
318
  placement: "end",
228
319
  avatar: () => {
229
- return userAvatar || /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons.UserOutlined, { className: (0, import_clsx.default)(styles.bg("#87d068"), styles.userAvatar) });
320
+ return userAvatar || /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
321
+ import_icons.UserOutlined,
322
+ {
323
+ className: (0, import_clsx.default)(styles.bg("#87d068"), styles.userAvatar)
324
+ }
325
+ );
230
326
  },
231
327
  classNames: {
232
328
  content: "user-content"
@@ -235,7 +331,12 @@ var XAiChatbot = (props) => {
235
331
  suggestion: {
236
332
  placement: "start",
237
333
  avatar: () => {
238
- return avatar || /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons.UserOutlined, { className: (0, import_clsx.default)(styles.bg("#fde3cf"), styles.userAvatar) });
334
+ return avatar || /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
335
+ import_icons.UserOutlined,
336
+ {
337
+ className: (0, import_clsx.default)(styles.bg("#fde3cf"), styles.userAvatar)
338
+ }
339
+ );
239
340
  },
240
341
  variant: "borderless"
241
342
  }
@@ -270,10 +371,31 @@ var XAiChatbot = (props) => {
270
371
  const confirmClear = () => {
271
372
  onClear == null ? void 0 : onClear();
272
373
  };
273
- const EmptyState = (0, import_react.useMemo)(() => () => empty || /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: styles.emptyWrapper, children: [
274
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src: emptyStateImage, alt: "空状态图标", className: styles.emptyImg }),
275
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: (0, import_clsx.default)(styles.text(16), styles.weight(600), styles.textColor("#343434")), children: emptyStateText })
276
- ] }), [emptyStateImage, emptyStateText]);
374
+ const EmptyState = (0, import_react.useMemo)(
375
+ () => () => empty || /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: styles.emptyWrapper, children: [
376
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
377
+ "img",
378
+ {
379
+ src: emptyStateImage,
380
+ alt: "空状态图标",
381
+ className: styles.emptyImg
382
+ }
383
+ ),
384
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
385
+ "div",
386
+ {
387
+ className: (0, import_clsx.default)(
388
+ styles.text(16),
389
+ styles.weight(600),
390
+ styles.textColor("#343434")
391
+ ),
392
+ children: emptyStateText
393
+ }
394
+ )
395
+ ] }),
396
+ // eslint-disable-next-line react-hooks/exhaustive-deps
397
+ [emptyStateImage, emptyStateText]
398
+ );
277
399
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
278
400
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_styles.GlobalStyle, {}),
279
401
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_markdown.default, {}),
@@ -286,7 +408,16 @@ var XAiChatbot = (props) => {
286
408
  role: rolesObject,
287
409
  className: styles.messageList,
288
410
  items: messages.map((msg) => {
289
- const { id, role, status, type, execute = [], thinks = "", extra = { noFooter: false }, stepContent } = msg;
411
+ const {
412
+ id,
413
+ role,
414
+ status,
415
+ type,
416
+ execute = [],
417
+ thinks = "",
418
+ extra = { noFooter: false },
419
+ stepContent
420
+ } = msg;
290
421
  if (role === import_XAiMessage.MessageRole.assistant) {
291
422
  lastMessageId.current = id;
292
423
  }
@@ -294,13 +425,7 @@ var XAiChatbot = (props) => {
294
425
  key: id,
295
426
  role,
296
427
  loading: status === import_XAiMessage.MessageStatus.init,
297
- header: () => messageTop || /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
298
- ActionHeader,
299
- {
300
- execute,
301
- thinks
302
- }
303
- ),
428
+ header: () => messageTop || /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ActionHeader, { execute, thinks }),
304
429
  content: (() => {
305
430
  var _a, _b;
306
431
  if (type === "TextMessage") {
@@ -361,7 +486,9 @@ var XAiChatbot = (props) => {
361
486
  onItemClick: (info) => {
362
487
  onSuggestMessageClick == null ? void 0 : onSuggestMessageClick(info == null ? void 0 : info.data, id);
363
488
  if (info.data.description) {
364
- onSend == null ? void 0 : onSend({ text: info.data.description });
489
+ onSend == null ? void 0 : onSend({
490
+ text: info.data.description
491
+ });
365
492
  }
366
493
  }
367
494
  }
@@ -394,7 +521,13 @@ var XAiChatbot = (props) => {
394
521
  )) });
395
522
  }
396
523
  if (role === import_XAiMessage.MessageRole.assistant && status !== import_XAiMessage.MessageStatus.failed) {
397
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MessageFooter, { data: msg, lastMessage: lastMessageId.current === id });
524
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
525
+ MessageFooter,
526
+ {
527
+ data: msg,
528
+ lastMessage: lastMessageId.current === id
529
+ }
530
+ );
398
531
  }
399
532
  };
400
533
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/components/XAiChatbot/index.tsx"],
4
- "sourcesContent": ["// 文件: components/XAiChatbot/index.tsx\n\nimport React, {\n useRef,\n useState,\n useMemo,\n} from 'react';\nimport {\n Tooltip,\n GetProp,\n Flex,\n} from 'antd';\nimport {\n Bubble,\n Prompts,\n Attachments,\n FileCard\n} from '@ant-design/x';\nimport {\n UserOutlined,\n RedoOutlined,\n CopyOutlined,\n DeleteOutlined,\n} from '@ant-design/icons';\nimport clsx from 'clsx';\nimport MarkdownIt from 'markdown-it';\nimport reactHtmlParser from 'react-html-parser';\nimport type { Attachment } from '@ant-design/x/es/attachments';\nimport MarkdownGlobalStyle from '@/styles/markdown';\nimport {\n MessageStatus,\n MessageRole,\n Messages,\n} from '@/types/XAiMessage';\nimport {\n XAiChatbotProps,\n ActionItem,\n} from '@/types/XAiChatbot';\nimport emptyIcon from '@/assets/empty.png';\nimport arrowUp from '@/assets/arrow-up.png';\nimport arrowDown from '@/assets/arrow-down.png';\nimport thinkIcon from '@/assets/think.png';\nimport groupIcon from '@/assets/group.png';\nimport arrowDownBlue from '@/assets/arrow-down-blue.png';\nimport { useChatbotContext } from '@/hooks/useProviderContext';\nimport { useStyles, GlobalStyle } from './styles';\nimport XAiSender from '../XAiSender';\nimport type { SendContent } from '@/types';\n\nconst md = new MarkdownIt({\n html: true,\n linkify: true,\n typographer: true,\n});\n\n// 自定义 link_open 渲染规则\nconst defaultRender = md.renderer.rules.link_open || ((tokens, idx, options, env, self) => {\n return self.renderToken(tokens, idx, options);\n});\n\n// a 标签打开规则\nmd.renderer.rules.link_open = (tokens, idx, options, env, self) => {\n // 添加 target=\"_blank\"\n const aIndex = tokens[idx].attrIndex('target');\n if (aIndex < 0) {\n tokens[idx].attrPush(['target', '_blank']);\n } else {\n tokens[idx].attrs![aIndex][1] = '_blank';\n }\n // 添加 rel=\"noopener noreferrer\"\n const relIndex = tokens[idx].attrIndex('rel');\n if (relIndex < 0) {\n tokens[idx].attrPush(['rel', 'noopener noreferrer']);\n } else {\n tokens[idx].attrs![relIndex][1] = 'noopener noreferrer';\n }\n return defaultRender(tokens, idx, options, env, self);\n};\n\nexport interface ActionHeaderProps {\n execute: any[];\n thinks: string;\n}\n\n// ActionHeader 组件\nexport const ActionHeader: React.FC<ActionHeaderProps> = ({ execute = [], thinks = '' }) => {\n const styles = useStyles();\n const [expanded, setExpanded] = useState(true);\n const [executeExpanded, setExecuteExpanded] = useState(false);\n\n // 关键修复:只要有思考内容或执行过程就显示,不要同时要求两者都有\n if (!thinks && (!execute || execute.length === 0)) return null;\n\n const last = execute[execute.length - 1] || {};\n const { name } = last;\n const icon = last?.icon || last?.extra?.icon;\n\n return (\n <div className={styles.actionHeaderWrapper}>\n {!expanded && (\n <div className={styles.actionTitle} onClick={() => setExpanded((v) => !v)}>\n <img src={thinkIcon} alt=\"icon\" className={styles.actionHeaderIcon} />\n <span className={styles.flex1}>运行过程</span>\n <img alt=\"展开icon\" src={arrowDown} className={styles.w('16px')} />\n </div>\n )}\n {expanded && (\n <div className={styles.actionHeaderDetail}>\n <div className={styles.actionDetailTitle} onClick={() => setExpanded((v) => !v)}>\n <img src={thinkIcon} alt=\"\" className={clsx(styles.w(14))} />\n <div className={clsx(styles.flex1, styles.pl(10))}>隐藏运行过程</div>\n <img alt=\"收起icon\" src={arrowUp} className={styles.w('16px')} />\n </div>\n\n {thinks && (\n <div className={styles.actionDetailContent} style={{ whiteSpace: 'pre-line' }}>\n {thinks}\n </div>\n )}\n\n {execute && execute.length > 0 && (\n <>\n {!executeExpanded && (\n <div className={styles.executeHiddenWrapper} onClick={() => setExecuteExpanded((v) => !v)}>\n {icon && <img src={icon} alt=\"icon\" className={styles.h(15)} />}\n <span className={styles.flex1}>{name}</span>\n <img alt=\"工具icon\" src={arrowDownBlue} className={styles.w('16px')} />\n </div>\n )}\n {executeExpanded && (\n <div className={styles.executeWrapper}>\n <div className={styles.executeTitle} onClick={() => setExecuteExpanded((v) => !v)}>\n <img src={groupIcon} alt=\"icon\" className={styles.executeHeaderIcon} />\n <span className={styles.flex1}>隐藏运行详情</span>\n <img alt=\"展开详情icon\" src={arrowUp} className={styles.w('16px')} />\n </div>\n <div className={styles.executeContent}>\n {execute.map((action: any, idx: number) => {\n const thinkIcon2 = action?.expandIcon || action?.extra?.expandIcon || action?.extra?.icon || action?.icon;\n const thinkCost = action?.cost || action?.extra?.cost;\n return (\n <div key={action.uniqueId || idx} className={styles.actionHeaderDetailItem}>\n {thinkIcon2 && <img src={thinkIcon2} alt=\"icon\" className={styles.actionHeaderIcon} />}\n <span>{action?.name}</span>\n <span className={styles.actionHeaderCost}>{thinkCost ? `${thinkCost}s` : ''}</span>\n </div>\n );\n })}\n </div>\n </div>\n )}\n </>\n )}\n </div>\n )}\n </div>\n );\n};\n\n// 默认消息功能区\nexport const defaultActions: ActionItem[] = [\n {\n key: 'redo',\n icon: <RedoOutlined />,\n tooltip: '重新生成',\n },\n {\n key: 'copy',\n icon: <CopyOutlined />,\n tooltip: '复制',\n },\n {\n key: 'delete',\n icon: <DeleteOutlined />,\n tooltip: '删除',\n },\n];\n\nconst XAiChatbot: React.FC<XAiChatbotProps> = (props) => {\n const styles = useStyles();\n // 使用新的 Hook 来处理 Provider 上下文\n const { mergedProps } = useChatbotContext(props);\n\n const {\n navbarShow = false,\n navbar,\n renderNavbar = null,\n clearBtnShow = true,\n inputShow = true,\n // renderMessageContent,\n // quickReplies = [],\n // quickRepliesVisible = true,\n // onQuickReplyClick,\n loading: propLoading = false,\n messageTooltip,\n avatar,\n userAvatar,\n messages: propMessages,\n text = '',\n footerTips = '',\n empty = null,\n emptyStateImage = emptyIcon,\n emptyStateText = '我的智能体',\n messageActions = defaultActions,\n onMessagesActionsCallback,\n // 点击帮助消息\n onSuggestMessageClick,\n onSend,\n onClear,\n onStop,\n providerId,\n // 消息顶部\n messageTop,\n enableUpload,\n uploadRequest,\n } = mergedProps as XAiChatbotProps;\n\n // 如果在 Provider 中,使用 Provider 的状态\n const messages = mergedProps.messages || propMessages || [];\n const loading = mergedProps.loading || propLoading;\n\n const [content, setContent] = useState<string>(text); // 输入框文本\n const [files, setFiles] = useState<Attachment[]>([]);\n const lastMessageId = useRef<string>('');\n const isScriptScrolling = useRef<boolean>(false);\n const chatId = providerId ? `za-chatbot-container-${providerId}` : 'za-chatbot-container';\n\n // 滚动到最底部\n const scrollToBottom = () => {\n isScriptScrolling.current = true;\n setTimeout(() => {\n const mainChatWrapper = document.getElementById(chatId);\n if (mainChatWrapper) {\n mainChatWrapper.scrollTop = mainChatWrapper?.scrollHeight;\n }\n isScriptScrolling.current = false;\n }, 0);\n };\n\n // 消息功能区组件\n const FooterActions: React.FC<{ data: Messages; lastMessage: boolean }> = ({ data, lastMessage = false }) => (\n <div className={clsx(styles.flex, styles.gap(13))}>\n {messageActions.map((action: ActionItem, index: number) => {\n if (!lastMessage && action.key === 'redo') return null;\n return (\n <Tooltip key={action.key} title={action.tooltip}>\n <span className={styles.cursor('pointer')} onClick={() => onMessagesActionsCallback?.(index, data)}>\n {action.icon}\n {action.render?.(index, data)}\n </span>\n </Tooltip>\n );\n })}\n </div>\n );\n\n // 消息底部区域\n const MessageFooter: React.FC<{ data: Messages; lastMessage: boolean }> = ({ data, lastMessage = false }) => (\n <>\n {messageTooltip?.(data)}\n <FooterActions data={data} lastMessage={lastMessage} />\n </>\n );\n\n // 聊天角色\n const rolesObject: GetProp<typeof Bubble.List, 'role'> = {\n assistant: {\n placement: 'start',\n avatar: () => {\n return avatar || <UserOutlined className={clsx(styles.bg('#fde3cf'), styles.userAvatar)} />;\n },\n typing: { step: 5, interval: 20, effect: 'typing' },\n style: {\n maxWidth: 600,\n },\n classNames: {\n content: 'assistant-content',\n },\n },\n user: {\n placement: 'end',\n avatar: () => {\n return userAvatar || <UserOutlined className={clsx(styles.bg('#87d068'), styles.userAvatar)} />;\n },\n classNames: {\n content: 'user-content',\n },\n },\n suggestion: {\n placement: 'start',\n avatar: () => {\n return avatar || <UserOutlined className={clsx(styles.bg('#fde3cf'), styles.userAvatar)} />;\n },\n variant: 'borderless',\n },\n };\n\n // 触发发送\n const handleSend = (obj: SendContent) => {\n // 直接使用合并后的 onSend,自动处理 Provider 和独立模式\n onSend?.(obj);\n setContent(''); // 发送后清空输入框内容\n setFiles([]); // 发送后清空文件\n scrollToBottom();\n };\n\n // 输出内容\n const handleChange = (str: string) => {\n setContent(str);\n };\n\n // 停止生成\n const handleStop = () => {\n onStop?.();\n };\n\n // 导航栏\n const NavBar: React.FC = () => {\n if (renderNavbar) {\n return renderNavbar();\n } if (navbar?.title) {\n return (\n <header className={styles.navbar}>\n {navbar.avatar && <img src={navbar.avatar} className={styles.avatar} alt=\"\" />}\n <div>\n <div className={styles.title}>{navbar.title}</div>\n <div className={styles.subtitle}>{navbar.subtitle}</div>\n </div>\n </header>\n );\n }\n return <></>;\n };\n\n // 确认清除\n const confirmClear = () => {\n onClear?.();\n };\n\n // 空状态\n const EmptyState = useMemo(() => () => (\n empty || (\n <div className={styles.emptyWrapper}>\n <img src={emptyStateImage} alt=\"空状态图标\" className={styles.emptyImg} />\n <div className={clsx(styles.text(16), styles.weight(600), styles.textColor('#343434'))}>{emptyStateText}</div>\n </div>\n )\n // eslint-disable-next-line react-hooks/exhaustive-deps\n ), [emptyStateImage, emptyStateText]);\n\n return (\n <>\n <GlobalStyle />\n <MarkdownGlobalStyle />\n <div id=\"x-ai-chatbot\" className={styles.wrapper}>\n { navbarShow && <NavBar /> }\n {/** 消息容器 */}\n <div className={styles.messageContainer}>\n {/* 消息列表主体 */}\n {\n messages?.length\n ? (\n <Bubble.List\n id={chatId}\n role={rolesObject}\n className={styles.messageList}\n items={messages.map((msg: any) => {\n const { id, role, status, type, execute = [], thinks = '', extra = { noFooter: false }, stepContent } = msg as Messages;\n // 最后一条 AI消息标识\n if (role === MessageRole.assistant) {\n lastMessageId.current = id;\n }\n // 会话内容\n const bubbleContent: any = {\n key: id,\n role,\n loading: status === MessageStatus.init,\n header: (() => messageTop\n || (\n <ActionHeader\n execute={execute}\n thinks={thinks}\n />\n )),\n content: (() => {\n // 文本消息\n if (type === 'TextMessage') {\n // 用户消息\n if (role === 'user') {\n return (\n <div\n className=\"ai-markdown-body\"\n style={{\n minWidth: 0,\n maxWidth: 600,\n }}\n >\n {msg.content?.text}\n </div>\n );\n }\n\n // 输出html字符串\n const html = md.render(msg.content?.text || '');\n // 生成React节点\n const htmlString = reactHtmlParser(html);\n return (\n <>\n {/* 输出阶段性回答内容 */}\n {stepContent?.length && stepContent.map((item) => {\n // 输出html字符串\n const html2 = md.render(item.content || '');\n // 生成React节点\n const stepHtmlString = reactHtmlParser(html2);\n return (\n <div\n key={item.id}\n className=\"ai-markdown-body step-content\"\n style={{\n minWidth: 0,\n maxWidth: 600,\n }}\n >\n <div>\n {stepHtmlString}\n </div>\n <div className={styles.stepLine} />\n </div>\n );\n })}\n {/** 输出最终回答内容 */}\n <div\n className=\"ai-markdown-body\"\n style={{\n minWidth: 0,\n maxWidth: 600,\n }}\n >\n {htmlString}\n </div>\n </>\n );\n }\n // 提示类型\n if (type === 'SuggestionMessage') {\n return (\n <Prompts\n vertical\n items={msg.content as any}\n onItemClick={(info) => {\n onSuggestMessageClick?.(info?.data, id);\n if (info.data.description) {\n onSend?.({ text: info.data.description as string });\n }\n }}\n />\n );\n }\n // 其他类型...\n return null;\n })(),\n };\n\n if (!extra.noFooter) {\n bubbleContent.footer = (() => {\n const msgFiles = msg.content?.files || [];\n if (role === MessageRole.user && msgFiles.length) {\n return (\n <Flex gap={8} wrap justify=\"flex-end\">\n {msgFiles.map((f: any) => (\n <FileCard\n styles={{\n file: f?.fileType === 'image' ? {\n width: 100,\n height: 100,\n } : {},\n }}\n key={f.fileId}\n {...f}\n name={f.fileName}\n size={f.fileSize}\n type={f.fileType}\n src={f.fileUrl}\n />\n ))}\n </Flex>\n );\n }\n if (role === MessageRole.assistant && status !== MessageStatus.failed) {\n return <MessageFooter data={msg as Messages} lastMessage={lastMessageId.current === id} />;\n }\n });\n }\n\n return bubbleContent;\n })}\n />\n )\n : (\n <EmptyState />\n )\n }\n </div>\n {/* 输入框 */}\n { inputShow && (\n <XAiSender\n value={content}\n loading={loading}\n footerTips={footerTips}\n clearBtnShow={clearBtnShow}\n enableUpload={enableUpload}\n files={files}\n onChangeFiles={setFiles}\n uploadRequest={uploadRequest}\n onChange={handleChange}\n onSubmit={handleSend}\n onStop={handleStop}\n onClear={confirmClear}\n />\n ) }\n </div>\n </>\n );\n};\n\nexport default XAiChatbot;\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["// 文件: components/XAiChatbot/index.tsx\n\nimport React, { useRef, useState, useMemo } from \"react\";\nimport { Tooltip, GetProp, Flex } from \"antd\";\nimport { Bubble, Prompts, FileCard } from \"@ant-design/x\";\nimport {\n UserOutlined,\n RedoOutlined,\n CopyOutlined,\n DeleteOutlined,\n} from \"@ant-design/icons\";\nimport clsx from \"clsx\";\nimport MarkdownIt from \"markdown-it\";\nimport reactHtmlParser from \"react-html-parser\";\nimport type { Attachment } from \"@ant-design/x/es/attachments\";\nimport MarkdownGlobalStyle from \"@/styles/markdown\";\nimport { MessageStatus, MessageRole, Messages } from \"@/types/XAiMessage\";\nimport { XAiChatbotProps, ActionItem } from \"@/types/XAiChatbot\";\nimport emptyIcon from \"@/assets/empty.png\";\nimport arrowUp from \"@/assets/arrow-up.png\";\nimport arrowDown from \"@/assets/arrow-down.png\";\nimport thinkIcon from \"@/assets/think.png\";\nimport groupIcon from \"@/assets/group.png\";\nimport arrowDownBlue from \"@/assets/arrow-down-blue.png\";\nimport { useChatbotContext } from \"@/hooks/useProviderContext\";\nimport { useStyles, GlobalStyle } from \"./styles\";\nimport XAiSender from \"../XAiSender\";\nimport type { SendContent } from \"@/types\";\n\nconst md = new MarkdownIt({\n html: true,\n linkify: true,\n typographer: true,\n});\n\n// 自定义 link_open 渲染规则\nconst defaultRender =\n md.renderer.rules.link_open ||\n ((tokens, idx, options, env, self) => {\n return self.renderToken(tokens, idx, options);\n });\n\n// a 标签打开规则\nmd.renderer.rules.link_open = (tokens, idx, options, env, self) => {\n // 添加 target=\"_blank\"\n const aIndex = tokens[idx].attrIndex(\"target\");\n if (aIndex < 0) {\n tokens[idx].attrPush([\"target\", \"_blank\"]);\n } else {\n tokens[idx].attrs![aIndex][1] = \"_blank\";\n }\n // 添加 rel=\"noopener noreferrer\"\n const relIndex = tokens[idx].attrIndex(\"rel\");\n if (relIndex < 0) {\n tokens[idx].attrPush([\"rel\", \"noopener noreferrer\"]);\n } else {\n tokens[idx].attrs![relIndex][1] = \"noopener noreferrer\";\n }\n return defaultRender(tokens, idx, options, env, self);\n};\n\nexport interface ActionHeaderProps {\n execute: any[];\n thinks: string;\n}\n\n// ActionHeader 组件\nexport const ActionHeader: React.FC<ActionHeaderProps> = ({\n execute = [],\n thinks = \"\",\n}) => {\n const styles = useStyles();\n const [expanded, setExpanded] = useState(true);\n const [executeExpanded, setExecuteExpanded] = useState(false);\n\n // 关键修复:只要有思考内容或执行过程就显示,不要同时要求两者都有\n if (!thinks && (!execute || execute.length === 0)) return null;\n\n const last = execute[execute.length - 1] || {};\n const { name } = last;\n const icon = last?.icon || last?.extra?.icon;\n\n return (\n <div className={styles.actionHeaderWrapper}>\n {!expanded && (\n <div\n className={styles.actionTitle}\n onClick={() => setExpanded((v) => !v)}\n >\n <img src={thinkIcon} alt=\"icon\" className={styles.actionHeaderIcon} />\n <span className={styles.flex1}>运行过程</span>\n <img alt=\"展开icon\" src={arrowDown} className={styles.w(\"16px\")} />\n </div>\n )}\n {expanded && (\n <div className={styles.actionHeaderDetail}>\n <div\n className={styles.actionDetailTitle}\n onClick={() => setExpanded((v) => !v)}\n >\n <img src={thinkIcon} alt=\"\" className={clsx(styles.w(14))} />\n <div className={clsx(styles.flex1, styles.pl(10))}>\n 隐藏运行过程\n </div>\n <img alt=\"收起icon\" src={arrowUp} className={styles.w(\"16px\")} />\n </div>\n\n {thinks && (\n <div\n className={styles.actionDetailContent}\n style={{ whiteSpace: \"pre-line\" }}\n >\n {thinks}\n </div>\n )}\n\n {execute && execute.length > 0 && (\n <>\n {!executeExpanded && (\n <div\n className={styles.executeHiddenWrapper}\n onClick={() => setExecuteExpanded((v) => !v)}\n >\n {icon && (\n <img src={icon} alt=\"icon\" className={styles.h(15)} />\n )}\n <span className={styles.flex1}>{name}</span>\n <img\n alt=\"工具icon\"\n src={arrowDownBlue}\n className={styles.w(\"16px\")}\n />\n </div>\n )}\n {executeExpanded && (\n <div className={styles.executeWrapper}>\n <div\n className={styles.executeTitle}\n onClick={() => setExecuteExpanded((v) => !v)}\n >\n <img\n src={groupIcon}\n alt=\"icon\"\n className={styles.executeHeaderIcon}\n />\n <span className={styles.flex1}>隐藏运行详情</span>\n <img\n alt=\"展开详情icon\"\n src={arrowUp}\n className={styles.w(\"16px\")}\n />\n </div>\n <div className={styles.executeContent}>\n {execute.map((action: any, idx: number) => {\n const thinkIcon2 =\n action?.expandIcon ||\n action?.extra?.expandIcon ||\n action?.extra?.icon ||\n action?.icon;\n const thinkCost = action?.cost || action?.extra?.cost;\n return (\n <div\n key={action.uniqueId || idx}\n className={styles.actionHeaderDetailItem}\n >\n {thinkIcon2 && (\n <img\n src={thinkIcon2}\n alt=\"icon\"\n className={styles.actionHeaderIcon}\n />\n )}\n <span>{action?.name}</span>\n <span className={styles.actionHeaderCost}>\n {thinkCost ? `${thinkCost}s` : \"\"}\n </span>\n </div>\n );\n })}\n </div>\n </div>\n )}\n </>\n )}\n </div>\n )}\n </div>\n );\n};\n\n// 默认消息功能区\nexport const defaultActions: ActionItem[] = [\n {\n key: \"redo\",\n icon: <RedoOutlined />,\n tooltip: \"重新生成\",\n },\n {\n key: \"copy\",\n icon: <CopyOutlined />,\n tooltip: \"复制\",\n },\n {\n key: \"delete\",\n icon: <DeleteOutlined />,\n tooltip: \"删除\",\n },\n];\n\nconst XAiChatbot: React.FC<XAiChatbotProps> = (props) => {\n const styles = useStyles();\n // 使用新的 Hook 来处理 Provider 上下文\n const { mergedProps } = useChatbotContext(props);\n\n const {\n navbarShow = false,\n navbar,\n renderNavbar = null,\n clearBtnShow = true,\n inputShow = true,\n // renderMessageContent,\n // quickReplies = [],\n // quickRepliesVisible = true,\n // onQuickReplyClick,\n loading: propLoading = false,\n messageTooltip,\n avatar,\n userAvatar,\n messages: propMessages,\n text = \"\",\n footerTips = \"\",\n empty = null,\n emptyStateImage = emptyIcon,\n emptyStateText = \"我的智能体\",\n messageActions = defaultActions,\n onMessagesActionsCallback,\n // 点击帮助消息\n onSuggestMessageClick,\n onSend,\n onClear,\n onStop,\n providerId,\n // 消息顶部\n messageTop,\n enableUpload,\n uploadRequest,\n } = mergedProps as XAiChatbotProps;\n\n // 如果在 Provider 中,使用 Provider 的状态\n const messages = mergedProps.messages || propMessages || [];\n const loading = mergedProps.loading || propLoading;\n\n const [content, setContent] = useState<string>(text); // 输入框文本\n const [files, setFiles] = useState<Attachment[]>([]);\n const lastMessageId = useRef<string>(\"\");\n const isScriptScrolling = useRef<boolean>(false);\n const chatId = providerId\n ? `za-chatbot-container-${providerId}`\n : \"za-chatbot-container\";\n\n // 滚动到最底部\n const scrollToBottom = () => {\n isScriptScrolling.current = true;\n setTimeout(() => {\n const mainChatWrapper = document.getElementById(chatId);\n if (mainChatWrapper) {\n mainChatWrapper.scrollTop = mainChatWrapper?.scrollHeight;\n }\n isScriptScrolling.current = false;\n }, 0);\n };\n\n // 消息功能区组件\n const FooterActions: React.FC<{ data: Messages; lastMessage: boolean }> = ({\n data,\n lastMessage = false,\n }) => (\n <div className={clsx(styles.flex, styles.gap(13))}>\n {messageActions.map((action: ActionItem, index: number) => {\n if (!lastMessage && action.key === \"redo\") return null;\n return (\n <Tooltip key={action.key} title={action.tooltip}>\n <span\n className={styles.cursor(\"pointer\")}\n onClick={() => onMessagesActionsCallback?.(index, data)}\n >\n {action.icon}\n {action.render?.(index, data)}\n </span>\n </Tooltip>\n );\n })}\n </div>\n );\n\n // 消息底部区域\n const MessageFooter: React.FC<{ data: Messages; lastMessage: boolean }> = ({\n data,\n lastMessage = false,\n }) => (\n <>\n {messageTooltip?.(data)}\n <FooterActions data={data} lastMessage={lastMessage} />\n </>\n );\n\n // 聊天角色\n const rolesObject: GetProp<typeof Bubble.List, \"role\"> = {\n assistant: {\n placement: \"start\",\n avatar: () => {\n return (\n avatar || (\n <UserOutlined\n className={clsx(styles.bg(\"#fde3cf\"), styles.userAvatar)}\n />\n )\n );\n },\n typing: { step: 5, interval: 20, effect: \"typing\" },\n style: {\n maxWidth: 600,\n },\n classNames: {\n content: \"assistant-content\",\n },\n },\n user: {\n placement: \"end\",\n avatar: () => {\n return (\n userAvatar || (\n <UserOutlined\n className={clsx(styles.bg(\"#87d068\"), styles.userAvatar)}\n />\n )\n );\n },\n classNames: {\n content: \"user-content\",\n },\n },\n suggestion: {\n placement: \"start\",\n avatar: () => {\n return (\n avatar || (\n <UserOutlined\n className={clsx(styles.bg(\"#fde3cf\"), styles.userAvatar)}\n />\n )\n );\n },\n variant: \"borderless\",\n },\n };\n\n // 触发发送\n const handleSend = (obj: SendContent) => {\n // 直接使用合并后的 onSend,自动处理 Provider 和独立模式\n onSend?.(obj);\n setContent(\"\"); // 发送后清空输入框内容\n setFiles([]); // 发送后清空文件\n scrollToBottom();\n };\n\n // 输出内容\n const handleChange = (str: string) => {\n setContent(str);\n };\n\n // 停止生成\n const handleStop = () => {\n onStop?.();\n };\n\n // 导航栏\n const NavBar: React.FC = () => {\n if (renderNavbar) {\n return renderNavbar();\n }\n if (navbar?.title) {\n return (\n <header className={styles.navbar}>\n {navbar.avatar && (\n <img src={navbar.avatar} className={styles.avatar} alt=\"\" />\n )}\n <div>\n <div className={styles.title}>{navbar.title}</div>\n <div className={styles.subtitle}>{navbar.subtitle}</div>\n </div>\n </header>\n );\n }\n return <></>;\n };\n\n // 确认清除\n const confirmClear = () => {\n onClear?.();\n };\n\n // 空状态\n const EmptyState = useMemo(\n () => () =>\n empty || (\n <div className={styles.emptyWrapper}>\n <img\n src={emptyStateImage}\n alt=\"空状态图标\"\n className={styles.emptyImg}\n />\n <div\n className={clsx(\n styles.text(16),\n styles.weight(600),\n styles.textColor(\"#343434\"),\n )}\n >\n {emptyStateText}\n </div>\n </div>\n ),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [emptyStateImage, emptyStateText],\n );\n\n return (\n <>\n <GlobalStyle />\n <MarkdownGlobalStyle />\n <div id=\"x-ai-chatbot\" className={styles.wrapper}>\n {navbarShow && <NavBar />}\n {/** 消息容器 */}\n <div className={styles.messageContainer}>\n {/* 消息列表主体 */}\n {messages?.length ? (\n <Bubble.List\n id={chatId}\n role={rolesObject}\n className={styles.messageList}\n items={messages.map((msg: any) => {\n const {\n id,\n role,\n status,\n type,\n execute = [],\n thinks = \"\",\n extra = { noFooter: false },\n stepContent,\n } = msg as Messages;\n // 最后一条 AI消息标识\n if (role === MessageRole.assistant) {\n lastMessageId.current = id;\n }\n // 会话内容\n const bubbleContent: any = {\n key: id,\n role,\n loading: status === MessageStatus.init,\n header: () =>\n messageTop || (\n <ActionHeader execute={execute} thinks={thinks} />\n ),\n content: (() => {\n // 文本消息\n if (type === \"TextMessage\") {\n // 用户消息\n if (role === \"user\") {\n return (\n <div\n className=\"ai-markdown-body\"\n style={{\n minWidth: 0,\n maxWidth: 600,\n }}\n >\n {msg.content?.text}\n </div>\n );\n }\n\n // 输出html字符串\n const html = md.render(msg.content?.text || \"\");\n // 生成React节点\n const htmlString = reactHtmlParser(html);\n return (\n <>\n {/* 输出阶段性回答内容 */}\n {stepContent?.length &&\n stepContent.map((item) => {\n // 输出html字符串\n const html2 = md.render(item.content || \"\");\n // 生成React节点\n const stepHtmlString = reactHtmlParser(html2);\n return (\n <div\n key={item.id}\n className=\"ai-markdown-body step-content\"\n style={{\n minWidth: 0,\n maxWidth: 600,\n }}\n >\n <div>{stepHtmlString}</div>\n <div className={styles.stepLine} />\n </div>\n );\n })}\n {/** 输出最终回答内容 */}\n <div\n className=\"ai-markdown-body\"\n style={{\n minWidth: 0,\n maxWidth: 600,\n }}\n >\n {htmlString}\n </div>\n </>\n );\n }\n // 提示类型\n if (type === \"SuggestionMessage\") {\n return (\n <Prompts\n vertical\n items={msg.content as any}\n onItemClick={(info) => {\n onSuggestMessageClick?.(info?.data, id);\n if (info.data.description) {\n onSend?.({\n text: info.data.description as string,\n });\n }\n }}\n />\n );\n }\n // 其他类型...\n return null;\n })(),\n };\n\n if (!extra.noFooter) {\n bubbleContent.footer = () => {\n const msgFiles = msg.content?.files || [];\n if (role === MessageRole.user && msgFiles.length) {\n return (\n <Flex gap={8} wrap justify=\"flex-end\">\n {msgFiles.map((f: any) => (\n <FileCard\n styles={{\n file:\n f?.fileType === \"image\"\n ? {\n width: 100,\n height: 100,\n }\n : {},\n }}\n key={f.fileId}\n {...f}\n name={f.fileName}\n size={f.fileSize}\n type={f.fileType}\n src={f.fileUrl}\n />\n ))}\n </Flex>\n );\n }\n if (\n role === MessageRole.assistant &&\n status !== MessageStatus.failed\n ) {\n return (\n <MessageFooter\n data={msg as Messages}\n lastMessage={lastMessageId.current === id}\n />\n );\n }\n };\n }\n\n return bubbleContent;\n })}\n />\n ) : (\n <EmptyState />\n )}\n </div>\n {/* 输入框 */}\n {inputShow && (\n <XAiSender\n value={content}\n loading={loading}\n footerTips={footerTips}\n clearBtnShow={clearBtnShow}\n enableUpload={enableUpload}\n files={files}\n onChangeFiles={setFiles}\n uploadRequest={uploadRequest}\n onChange={handleChange}\n onSubmit={handleSend}\n onStop={handleStop}\n onClear={confirmClear}\n />\n )}\n </div>\n </>\n );\n};\n\nexport default XAiChatbot;\n"],
5
+ "mappings": "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",
6
6
  "names": ["MarkdownIt", "thinkIcon", "arrowDown", "clsx", "arrowUp", "arrowDownBlue", "groupIcon", "_a", "emptyIcon", "MarkdownGlobalStyle", "reactHtmlParser", "XAiSender"]
7
7
  }
@@ -74,6 +74,8 @@ export interface SenderUIProps {
74
74
  allowUpload?: boolean;
75
75
  /** 是否启用 Sender 自身的拖拽上传,设为 false 时由外层(如 DefaultLayout)管理拖拽 */
76
76
  draggable?: boolean;
77
+ /** 是否显示输入框顶部渐变遮罩(通过 ::before 伪元素实现),默认开启 */
78
+ showMask?: boolean;
77
79
  loading?: boolean;
78
80
  disabled?: boolean;
79
81
  /** 受控:输入框的值 */
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/types/XAdkSender.ts"],
4
- "sourcesContent": ["// types/XAdkSender.ts\nimport React from \"react\";\n\nexport interface UploadFileResult {\n fileName?: string;\n fileId?: string | number;\n tempUrl?: string;\n url?: string;\n fileUrl?: string;\n fileType?: string;\n fileSize?: number;\n mimeType?: string;\n [key: string]: any;\n}\n\nexport interface UploadSuccessResponse {\n data?: UploadFileResult | UploadFileResult[];\n [key: string]: any;\n}\n\ninterface uploadRequestProps {\n (options: {\n file: File;\n onProgress?: (e: { percent: number }) => void;\n onSuccess?: (\n response: UploadFileResult | UploadFileResult[] | UploadSuccessResponse,\n ) => void;\n onError?: (error: Error) => void;\n }): Promise<void> | void;\n}\n\nexport type UploadRequestFn = uploadRequestProps;\n\nexport interface ServerFile {\n fileName: string;\n fileId: string | number;\n tempUrl: string;\n type: string;\n size?: number;\n mimeType: string;\n raw?: UploadFileResult;\n}\n\nexport interface LocalFile {\n id: string;\n uid: string;\n name: string;\n file: File;\n size: number;\n type: string;\n progress: number;\n status: \"pending\" | \"uploading\" | \"success\" | \"error\";\n // 服务器返回字段\n fileId?: string | number;\n tempUrl?: string;\n response?: any;\n errorMessage?: string; // 上传错误信息\n}\n\nexport type FileValidator = (\n file: File,\n context: { files: LocalFile[] },\n) => string | null;\n\nexport interface ActionsComponents {\n SendButton: React.ComponentType<any>;\n UploadButton: React.ComponentType<any>;\n ClearButton: React.ComponentType<any>;\n}\n\nexport type SlotRenderFunction = (\n oriNode: React.ReactNode,\n info: { components: ActionsComponents },\n) => React.ReactNode | false;\n\n// 上传相关\nexport interface UploaderCoreProps {\n uploadRequest?: uploadRequestProps;\n\n maxFileSize?: number;\n allowedFileTypes?: string[];\n maxFiles?: number;\n\n validators?: FileValidator[];\n\n // 数据层回调\n onFilesChange?: (files: LocalFile[]) => void;\n onUploadSuccess?: (file: LocalFile) => void;\n onUploadError?: (file: LocalFile, error: Error) => void;\n}\n\n// UI 相关\nexport interface SenderUIProps {\n clearBtnShow?: boolean;\n allowUpload?: boolean;\n /** 是否启用 Sender 自身的拖拽上传,设为 false 时由外层(如 DefaultLayout)管理拖拽 */\n draggable?: boolean;\n loading?: boolean;\n disabled?: boolean; // 只读状态\n /** 受控:输入框的值 */\n value?: string;\n /** 非受控:输入框默认值 */\n defaultValue?: string;\n onClear?: () => void;\n onChange?: (value: string) => void;\n onSubmit?: (data: { text: string; files: ServerFile[] }) => void;\n onStop?: () => void;\n\n /** 自定义发送按钮渲染 */\n sendButtonRender?: (info: {\n loading: boolean;\n disabled: boolean;\n /** 当前是否可以发送(文本非空或有已上传的文件) */\n canSend: boolean;\n onSend: () => void;\n onStop?: () => void;\n }) => React.ReactNode;\n\n // UI插槽功能\n /** 后缀内容,默认展示操作按钮,设为 false 时不显示 */\n suffix?: React.ReactNode | false | SlotRenderFunction;\n /** 头部面板 */\n header?: React.ReactNode | false | SlotRenderFunction;\n /** 前缀内容 */\n prefix?: React.ReactNode | false | SlotRenderFunction;\n /** 底部内容 */\n footer?: React.ReactNode | false | SlotRenderFunction;\n}\n\nexport type XAdkSenderProps = SenderUIProps & UploaderCoreProps;\n\nexport interface XAdkSenderHandle {\n addFiles: (files: File[]) => void;\n}\n"],
4
+ "sourcesContent": ["// types/XAdkSender.ts\nimport React from \"react\";\n\nexport interface UploadFileResult {\n fileName?: string;\n fileId?: string | number;\n tempUrl?: string;\n url?: string;\n fileUrl?: string;\n fileType?: string;\n fileSize?: number;\n mimeType?: string;\n [key: string]: any;\n}\n\nexport interface UploadSuccessResponse {\n data?: UploadFileResult | UploadFileResult[];\n [key: string]: any;\n}\n\ninterface uploadRequestProps {\n (options: {\n file: File;\n onProgress?: (e: { percent: number }) => void;\n onSuccess?: (\n response: UploadFileResult | UploadFileResult[] | UploadSuccessResponse,\n ) => void;\n onError?: (error: Error) => void;\n }): Promise<void> | void;\n}\n\nexport type UploadRequestFn = uploadRequestProps;\n\nexport interface ServerFile {\n fileName: string;\n fileId: string | number;\n tempUrl: string;\n type: string;\n size?: number;\n mimeType: string;\n raw?: UploadFileResult;\n}\n\nexport interface LocalFile {\n id: string;\n uid: string;\n name: string;\n file: File;\n size: number;\n type: string;\n progress: number;\n status: \"pending\" | \"uploading\" | \"success\" | \"error\";\n // 服务器返回字段\n fileId?: string | number;\n tempUrl?: string;\n response?: any;\n errorMessage?: string; // 上传错误信息\n}\n\nexport type FileValidator = (\n file: File,\n context: { files: LocalFile[] },\n) => string | null;\n\nexport interface ActionsComponents {\n SendButton: React.ComponentType<any>;\n UploadButton: React.ComponentType<any>;\n ClearButton: React.ComponentType<any>;\n}\n\nexport type SlotRenderFunction = (\n oriNode: React.ReactNode,\n info: { components: ActionsComponents },\n) => React.ReactNode | false;\n\n// 上传相关\nexport interface UploaderCoreProps {\n uploadRequest?: uploadRequestProps;\n\n maxFileSize?: number;\n allowedFileTypes?: string[];\n maxFiles?: number;\n\n validators?: FileValidator[];\n\n // 数据层回调\n onFilesChange?: (files: LocalFile[]) => void;\n onUploadSuccess?: (file: LocalFile) => void;\n onUploadError?: (file: LocalFile, error: Error) => void;\n}\n\n// UI 相关\nexport interface SenderUIProps {\n clearBtnShow?: boolean;\n allowUpload?: boolean;\n /** 是否启用 Sender 自身的拖拽上传,设为 false 时由外层(如 DefaultLayout)管理拖拽 */\n draggable?: boolean;\n /** 是否显示输入框顶部渐变遮罩(通过 ::before 伪元素实现),默认开启 */\n showMask?: boolean;\n loading?: boolean;\n disabled?: boolean; // 只读状态\n /** 受控:输入框的值 */\n value?: string;\n /** 非受控:输入框默认值 */\n defaultValue?: string;\n onClear?: () => void;\n onChange?: (value: string) => void;\n onSubmit?: (data: { text: string; files: ServerFile[] }) => void;\n onStop?: () => void;\n\n /** 自定义发送按钮渲染 */\n sendButtonRender?: (info: {\n loading: boolean;\n disabled: boolean;\n /** 当前是否可以发送(文本非空或有已上传的文件) */\n canSend: boolean;\n onSend: () => void;\n onStop?: () => void;\n }) => React.ReactNode;\n\n // UI插槽功能\n /** 后缀内容,默认展示操作按钮,设为 false 时不显示 */\n suffix?: React.ReactNode | false | SlotRenderFunction;\n /** 头部面板 */\n header?: React.ReactNode | false | SlotRenderFunction;\n /** 前缀内容 */\n prefix?: React.ReactNode | false | SlotRenderFunction;\n /** 底部内容 */\n footer?: React.ReactNode | false | SlotRenderFunction;\n}\n\nexport type XAdkSenderProps = SenderUIProps & UploaderCoreProps;\n\nexport interface XAdkSenderHandle {\n addFiles: (files: File[]) => void;\n}\n"],
5
5
  "mappings": ";;;;;;;;;;;;;;;AAAA;AAAA;",
6
6
  "names": []
7
7
  }
@@ -159,6 +159,28 @@ var XAdkChatbot = /*#__PURE__*/forwardRef(function (_ref, ref) {
159
159
  }
160
160
  }, [loading, messages]);
161
161
 
162
+ // loading 结束时(流式输出完成),操作栏(metaFooter)会渲染出来增加高度,
163
+ // 需要延迟滚动到底部,确保操作栏可见
164
+ var prevLoadingRef = useRef(loading);
165
+ useEffect(function () {
166
+ var wasLoading = prevLoadingRef.current;
167
+ prevLoadingRef.current = loading;
168
+ if (!wasLoading || loading) return; // 只在 loading true → false 时触发
169
+ if (userHasScrolledRef.current) return;
170
+ if (!messages.length) return;
171
+
172
+ // 延迟等待操作栏 DOM 渲染完成后再滚动
173
+ var timer = setTimeout(function () {
174
+ var el = listRef.current;
175
+ if (el) {
176
+ el.scrollTop = el.scrollHeight;
177
+ }
178
+ }, 50);
179
+ return function () {
180
+ return clearTimeout(timer);
181
+ };
182
+ }, [loading, messages]);
183
+
162
184
  // 处理滚动事件
163
185
  var handleScroll = useCallback(function () {
164
186
  var el = listRef.current;