@myun/gimi-chat 0.7.2 → 0.7.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.
@@ -28,7 +28,7 @@ export var KnowledgeIconComponent = function KnowledgeIconComponent(_ref2) {
28
28
  var lastMessageId = useAppSelector(function (state) {
29
29
  var list = state.gimiMenu.messageList;
30
30
  if (!list || list.length === 0) return undefined;
31
- return list[list.length - 1].messageId;
31
+ return list[list.length - 1].id;
32
32
  });
33
33
  var isMsgRecieving = useAppSelector(function (state) {
34
34
  return state.gimiMenu.isMsgRecieving;
@@ -14,6 +14,7 @@ interface Iprops {
14
14
  stopTTSByText: () => void;
15
15
  model: 'sidebar' | 'fullscreen';
16
16
  onRegenerateClick?: () => void;
17
+ containerRef: React.RefObject<HTMLDivElement>;
17
18
  }
18
19
  declare const MessageList: React.FC<Iprops & MessageConfig>;
19
20
  export default MessageList;
@@ -1,10 +1,16 @@
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 _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
3
+ 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."); }
4
+ 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); }
5
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
6
+ 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; } }
7
+ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
2
8
  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; }
3
9
  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; }
4
10
  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; }
5
11
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
6
12
  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); }
7
- import React from 'react';
13
+ import React, { useCallback, useEffect, useState } from 'react';
8
14
  import classNames from 'classnames';
9
15
  import styles from "./index.module.css";
10
16
  import { Spin } from '@douyinfe/semi-ui';
@@ -12,12 +18,12 @@ import { References } from "../reference-content";
12
18
  import { replaceBraces } from "../../utils/tools";
13
19
  import UploadList from "../upload-list";
14
20
  import AnswerItem from "../answer-item";
15
- import { useCallback } from 'react';
16
21
  import LottieImg from "../lottie-img";
17
22
  import { useGimiFileUpload } from "../../hooks/useFile";
18
23
  import { FileStatus } from "../../interfaces/fileInterface";
19
24
  import useChatActions from "../../hooks/useChatActions";
20
25
  import CopyButton from "../message-actions/CopyButton";
26
+ import { Virtuoso } from 'react-virtuoso';
21
27
  var MessageList = function MessageList(_ref) {
22
28
  var chatList = _ref.chatList,
23
29
  handleSend = _ref.handleSend,
@@ -48,7 +54,8 @@ var MessageList = function MessageList(_ref) {
48
54
  _ref$messageLayout = _ref.messageLayout,
49
55
  messageLayout = _ref$messageLayout === void 0 ? 'center' : _ref$messageLayout,
50
56
  _ref$messageStyle = _ref.messageStyle,
51
- messageStyle = _ref$messageStyle === void 0 ? {} : _ref$messageStyle;
57
+ messageStyle = _ref$messageStyle === void 0 ? {} : _ref$messageStyle,
58
+ containerRef = _ref.containerRef;
52
59
  var _useGimiFileUpload = useGimiFileUpload(),
53
60
  handleSSEFileAnalyize = _useGimiFileUpload.handleSSEFileAnalyize,
54
61
  fileUpload = _useGimiFileUpload.fileUpload;
@@ -109,19 +116,23 @@ var MessageList = function MessageList(_ref) {
109
116
  }
110
117
  return _objectSpread(_objectSpread({}, style), messageStyle);
111
118
  };
112
- return /*#__PURE__*/React.createElement("div", {
113
- className: classNames(styles.main),
114
- style: buildStyle()
115
- }, /*#__PURE__*/React.createElement("div", {
116
- className: classNames(model === 'sidebar' ? styles.small_container : styles.container)
117
- }, chatList.length > 0 && /*#__PURE__*/React.createElement("div", {
118
- className: styles.textWrap
119
- }, chatList.map(function (v) {
119
+ var _useState = useState(null),
120
+ _useState2 = _slicedToArray(_useState, 2),
121
+ scrollParent = _useState2[0],
122
+ setScrollParent = _useState2[1];
123
+ useEffect(function () {
124
+ if (containerRef.current) {
125
+ setScrollParent(containerRef.current);
126
+ }
127
+ }, [containerRef]);
128
+ var renderItem = useCallback(function (_, v) {
120
129
  var _v$quoteTeachModelLis, _v$quoteProductList;
130
+ if (!v || v.isSystemAuto === 1) {
131
+ return /*#__PURE__*/React.createElement("div", null);
132
+ }
121
133
  return /*#__PURE__*/React.createElement("div", {
122
134
  key: v.id
123
- }, v.isSystemAuto !== 1 && /*#__PURE__*/React.createElement("div", {
124
- key: String(v.id),
135
+ }, /*#__PURE__*/React.createElement("div", {
125
136
  className: classNames(styles.textItem, _defineProperty({}, styles.question, (v === null || v === void 0 ? void 0 : v.type) === 0)),
126
137
  onMouseLeave: function onMouseLeave() {
127
138
  return chatUI.setShowCopyId(0);
@@ -138,10 +149,7 @@ var MessageList = function MessageList(_ref) {
138
149
  quoteTeachModelList: v.quoteTeachModelList
139
150
  }), v.content && /*#__PURE__*/React.createElement("div", {
140
151
  className: styles.title
141
- }, replaceBraces(v.content)), v.messageFiles &&
142
- /*#__PURE__*/
143
- // 增加fileUrl校验,确保文件已上传
144
- React.createElement("div", {
152
+ }, replaceBraces(v.content)), v.messageFiles && /*#__PURE__*/React.createElement("div", {
145
153
  className: styles.listBox
146
154
  }, /*#__PURE__*/React.createElement(UploadList, {
147
155
  file: v.messageFiles,
@@ -182,6 +190,21 @@ var MessageList = function MessageList(_ref) {
182
190
  reasoningTitle: reasoningTitle,
183
191
  model: model
184
192
  })));
193
+ }, [chatUI, hideUserMessage, showOpera, onCopyCallback, onSucessExcel, onFailureExcel, onRetryExcel, showCommend, handleClickPromptWord, handleShowCourse, handleClickAskList, playTTSByText, stopTTSByText, isPlaying, onRegenerateClick, enableCopy, enableLike, enableUnLike, enableRegenerate, enableVoicePlay, onDownloadCallback, reasoningTitle, model, handleReTry, onLikeCallback, onUnLikeCallback]);
194
+ return /*#__PURE__*/React.createElement("div", {
195
+ className: classNames(styles.main),
196
+ style: buildStyle()
197
+ }, /*#__PURE__*/React.createElement("div", {
198
+ className: classNames(model === 'sidebar' ? styles.small_container : styles.container)
199
+ }, chatList.length > 0 && /*#__PURE__*/React.createElement("div", {
200
+ className: styles.textWrap
201
+ }, /*#__PURE__*/React.createElement(Virtuoso, {
202
+ style: {
203
+ height: '100%'
204
+ },
205
+ customScrollParent: scrollParent || undefined,
206
+ data: chatList,
207
+ itemContent: renderItem
185
208
  }), msgLoading && /*#__PURE__*/React.createElement("div", {
186
209
  className: styles.answerLoading
187
210
  }, /*#__PURE__*/React.createElement(LottieImg, {
@@ -228,11 +228,15 @@ var CommonChat = /*#__PURE__*/React.forwardRef(function (props, ref) {
228
228
  questionList: (agentObj === null || agentObj === void 0 ? void 0 : agentObj.questionList) || [],
229
229
  onQuickSend: handleInputSend,
230
230
  layout: 'vertical'
231
- }), isMoreLoading ? /*#__PURE__*/React.createElement("div", {
231
+ }), isMoreLoading && messageList.length === 0 ? /*#__PURE__*/React.createElement("div", {
232
232
  style: {
233
233
  height: '100%'
234
234
  }
235
- }, /*#__PURE__*/React.createElement(AiLoading, null)) : /*#__PURE__*/React.createElement(MessageList, _extends({
235
+ }, /*#__PURE__*/React.createElement(AiLoading, null)) : /*#__PURE__*/React.createElement(React.Fragment, null, isMoreLoading && messageList.length > 0 && /*#__PURE__*/React.createElement("div", {
236
+ style: {
237
+ width: '100%'
238
+ }
239
+ }, /*#__PURE__*/React.createElement(AiLoading, null)), /*#__PURE__*/React.createElement(MessageList, _extends({
236
240
  chatList: messageList || defaultMessages,
237
241
  handleSend: handleSend,
238
242
  inputModelRef: inputModelRef,
@@ -245,8 +249,9 @@ var CommonChat = /*#__PURE__*/React.forwardRef(function (props, ref) {
245
249
  model: model,
246
250
  isPlaying: isPlaying,
247
251
  playTTSByText: playTTSByText,
248
- stopTTSByText: stopTTSByText
249
- }, props.messageConfig)), /*#__PURE__*/React.createElement(SearchCourseList, {
252
+ stopTTSByText: stopTTSByText,
253
+ containerRef: containerRef
254
+ }, props.messageConfig))), /*#__PURE__*/React.createElement(SearchCourseList, {
250
255
  courseList: searchedCourseList,
251
256
  onMoreClick: triggerSearchCourseListSidebar
252
257
  })), showBackBottom && /*#__PURE__*/React.createElement("div", {
@@ -256,7 +261,7 @@ var CommonChat = /*#__PURE__*/React.forwardRef(function (props, ref) {
256
261
  }
257
262
  }, /*#__PURE__*/React.createElement(IconChevronDown, {
258
263
  size: "large"
259
- }))), showInput && !isMoreLoading && /*#__PURE__*/React.createElement(ChatInput, _extends({
264
+ }))), showInput && (messageList.length > 0 || !isMoreLoading) && /*#__PURE__*/React.createElement(ChatInput, _extends({
260
265
  ref: chatInputRef,
261
266
  onSend: handleInputSend,
262
267
  disabled: disableSend || isMoreLoading,
@@ -1,8 +1,9 @@
1
1
  import React from 'react';
2
2
  import { IChatMessageItem } from '../interfaces/chatMessage';
3
- declare const useChatHistory: (checkUnfinishedMessage: (chatList: IChatMessageItem[]) => Promise<void>, scrollBottomForce: () => void, containerRef: React.RefObject<HTMLDivElement>) => {
3
+ declare const useChatHistory: (checkUnfinishedMessage: (chatList: IChatMessageItem[]) => Promise<void>, scrollBottomForce: (animate?: boolean) => void, containerRef: React.RefObject<HTMLDivElement>) => {
4
4
  getContentMessageList: (pageIndex?: number, curPageSize?: number) => Promise<void>;
5
5
  isMoreLoading: boolean;
6
6
  hasMore: React.MutableRefObject<boolean>;
7
+ loadMore: () => void;
7
8
  };
8
9
  export default useChatHistory;
@@ -4,20 +4,20 @@ function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableTo
4
4
  function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
5
5
  function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
6
6
  function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
7
- 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); } }
8
- 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); }); }; }
9
7
  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; }
10
8
  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; }
11
9
  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; }
12
10
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
13
11
  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); }
12
+ 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); } }
13
+ 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); }); }; }
14
14
  function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
15
15
  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."); }
16
16
  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
17
  function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
18
18
  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; } }
19
19
  function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
20
- import React, { useCallback, useEffect, useRef, useLayoutEffect } from 'react';
20
+ import React, { useCallback, useEffect, useRef } from 'react';
21
21
  import { useAppDispatch, useAppSelector } from "../store/hooks";
22
22
  import { setMessageList } from "../store/slices/gimiMenuSlice";
23
23
  import { useContext } from 'react';
@@ -71,57 +71,24 @@ var useChatHistory = function useChatHistory(checkUnfinishedMessage, scrollBotto
71
71
  var conversationIdRef = useRef(conversationId);
72
72
  var businessParamsRef = useRef(businessParams);
73
73
  var historyScrollRef = useRef(null);
74
+ var lastLoadMoreAtRef = useRef(0);
75
+ var lastTouchYRef = useRef(null);
74
76
  messageListRef.current = messageList;
75
77
  isMsgRecievingRef.current = isMsgRecieving;
76
78
  agentObjRef.current = agentObj;
77
79
  isMoreLoadingRef.current = isMoreLoading;
78
80
  conversationIdRef.current = conversationId;
79
81
  businessParamsRef.current = businessParams;
80
-
81
- // 处理加载历史后的滚动补偿
82
- useLayoutEffect(function () {
83
- if (historyScrollRef.current && containerRef.current && !isMoreLoading) {
84
- var _historyScrollRef$cur = historyScrollRef.current,
85
- height = _historyScrollRef$cur.height,
86
- top = _historyScrollRef$cur.top;
87
- var container = containerRef.current;
88
- var newHeight = container.scrollHeight;
89
- var heightDiff = newHeight - height;
90
-
91
- // 只有当高度确实增加时才调整滚动位置,且只有当增加的高度大于阈值时才认为加载了新内容
92
- if (heightDiff > 0) {
93
- // 使用 requestAnimationFrame 确保在渲染后执行滚动调整
94
- requestAnimationFrame(function () {
95
- container.scrollTop = top + heightDiff;
96
- });
97
- }
98
- historyScrollRef.current = null;
99
- }
100
- }, [messageList, isMoreLoading, containerRef]);
101
-
102
- // 处理滚动事件
103
82
  useEffect(function () {
104
- var container = containerRef.current;
105
- if (!container) return;
106
- var handleScroll = throttle(function () {
107
- var scrollTop = container.scrollTop;
108
- if (scrollTop < 50 && !isMoreLoadingRef.current && hasMore.current && !isMsgRecievingRef.current && conversationIdRef.current && !isMoreLoadingRef.current) {
109
- setIsMoreLoading(true); // 加锁,防止重复请求
110
- setParam(function (prev) {
111
- var newPageIndex = prev.pageIndex + 1;
112
- // eslint-disable-next-line @typescript-eslint/no-use-before-define
113
- getContentMessageList(newPageIndex, prev.pageSize); // 使用新值
114
- return _objectSpread(_objectSpread({}, prev), {}, {
115
- pageIndex: newPageIndex
116
- });
117
- });
118
- }
119
- }, 200);
120
- container.addEventListener('scroll', handleScroll);
121
- return function () {
122
- return container.removeEventListener('scroll', handleScroll);
123
- };
124
- }, []);
83
+ if (!conversationId) {
84
+ hasMore.current = false;
85
+ setIsMoreLoading(false);
86
+ setParam({
87
+ pageIndex: 1,
88
+ pageSize: 10
89
+ });
90
+ }
91
+ }, [conversationId]);
125
92
 
126
93
  // 获取对话记录
127
94
  var getContentMessageList = useCallback( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
@@ -158,13 +125,14 @@ var useChatHistory = function useChatHistory(checkUnfinishedMessage, scrollBotto
158
125
  botId: currentAgentObj === null || currentAgentObj === void 0 ? void 0 : currentAgentObj.botId
159
126
  }, currentBusinessParams)
160
127
  };
128
+ isMoreLoadingRef.current = true;
161
129
  setIsMoreLoading(true);
162
- _context.next = 10;
130
+ _context.next = 11;
163
131
  return getMessageList(params);
164
- case 10:
132
+ case 11:
165
133
  res = _context.sent;
166
134
  if (!(res && res.status === 0)) {
167
- _context.next = 36;
135
+ _context.next = 37;
168
136
  break;
169
137
  }
170
138
  resData = formatFields(res.result.data, res.result.first ? [] : currentMessageList) || [];
@@ -179,21 +147,24 @@ var useChatHistory = function useChatHistory(checkUnfinishedMessage, scrollBotto
179
147
  }
180
148
  hasMore.current = res.result.last === undefined ? false : !res.result.last;
181
149
  if (!res.result.first) {
182
- _context.next = 26;
150
+ _context.next = 27;
183
151
  break;
184
152
  }
185
153
  dispatch(setMessageList({
186
154
  messageList: _newResData
187
155
  }));
188
- _context.next = 23;
156
+ _context.next = 24;
189
157
  return checkUnfinishedMessage(_newResData);
190
- case 23:
158
+ case 24:
191
159
  setTimeout(function () {
192
- scrollBottomForce();
160
+ scrollBottomForce(true);
161
+ setTimeout(function () {
162
+ scrollBottomForce(true);
163
+ }, 50);
193
164
  }, 0);
194
- _context.next = 34;
165
+ _context.next = 35;
195
166
  break;
196
- case 26:
167
+ case 27:
197
168
  container = containerRef.current;
198
169
  if (container) {
199
170
  historyScrollRef.current = {
@@ -205,43 +176,134 @@ var useChatHistory = function useChatHistory(checkUnfinishedMessage, scrollBotto
205
176
  // 2. 更新数据
206
177
  // 判断是否需要重写推荐列表
207
178
  if (!((currentAgentObj === null || currentAgentObj === void 0 ? void 0 : currentAgentObj.isEnableRelated) === 1 && !((_lastUserRequestMessa = lastUserRequestMessage) !== null && _lastUserRequestMessa !== void 0 && _lastUserRequestMessa.relatedResourceList) && ((lastMessage === null || lastMessage === void 0 ? void 0 : lastMessage.moduleType) === 'end' || (lastMessage === null || lastMessage === void 0 ? void 0 : lastMessage.moduleType) === 'COMPLETED'))) {
208
- _context.next = 33;
179
+ _context.next = 34;
209
180
  break;
210
181
  }
211
- _context.next = 31;
182
+ _context.next = 32;
212
183
  return rewriteRecommendListFormHistory(newChatList, lastUserRequestMessage.chatId);
213
- case 31:
214
- _context.next = 34;
184
+ case 32:
185
+ _context.next = 35;
215
186
  break;
216
- case 33:
187
+ case 34:
217
188
  dispatch(setMessageList({
218
189
  messageList: newChatList
219
190
  }));
220
- case 34:
221
- _context.next = 37;
191
+ case 35:
192
+ _context.next = 38;
222
193
  break;
223
- case 36:
194
+ case 37:
224
195
  if (res.status === 1034) {
225
196
  Toast.error(res.message || '获取历史记录失败');
226
197
  }
227
- case 37:
198
+ case 38:
199
+ isMoreLoadingRef.current = false;
228
200
  setIsMoreLoading(false);
229
- _context.next = 43;
201
+ _context.next = 47;
230
202
  break;
231
- case 40:
232
- _context.prev = 40;
203
+ case 42:
204
+ _context.prev = 42;
233
205
  _context.t0 = _context["catch"](5);
234
206
  console.error(_context.t0);
235
- case 43:
207
+ isMoreLoadingRef.current = false;
208
+ setIsMoreLoading(false);
209
+ case 47:
236
210
  case "end":
237
211
  return _context.stop();
238
212
  }
239
- }, _callee, null, [[5, 40]]);
240
- })), []);
213
+ }, _callee, null, [[5, 42]]);
214
+ })), [checkUnfinishedMessage, containerRef, dispatch, getMessageList, param.pageIndex, param.pageSize, rewriteRecommendListFormHistory, scrollBottomForce]);
215
+ var loadMore = useCallback(function () {
216
+ if (!hasMore.current || isMoreLoadingRef.current || isMsgRecievingRef.current || !conversationIdRef.current) {
217
+ return;
218
+ }
219
+ isMoreLoadingRef.current = true;
220
+ setIsMoreLoading(true);
221
+ setParam(function (prev) {
222
+ var newPageIndex = prev.pageIndex + 1;
223
+ getContentMessageList(newPageIndex, prev.pageSize);
224
+ return _objectSpread(_objectSpread({}, prev), {}, {
225
+ pageIndex: newPageIndex
226
+ });
227
+ });
228
+ }, [getContentMessageList]);
229
+ useEffect(function () {
230
+ var container = containerRef.current;
231
+ if (!container) return;
232
+ var threshold = 40;
233
+ var cooldownMs = 250;
234
+ var tryLoadMore = function tryLoadMore() {
235
+ var now = Date.now();
236
+ if (now - lastLoadMoreAtRef.current < cooldownMs) return;
237
+ lastLoadMoreAtRef.current = now;
238
+ loadMore();
239
+ };
240
+ var handleScroll = throttle(function () {
241
+ if (!containerRef.current) return;
242
+ var scrollTop = containerRef.current.scrollTop;
243
+ if (scrollTop <= threshold) tryLoadMore();
244
+ }, 120);
245
+ var handleWheel = function handleWheel(e) {
246
+ var current = containerRef.current;
247
+ if (!current) return;
248
+ if (e.deltaY >= -5) return;
249
+ if (current.scrollTop <= threshold) tryLoadMore();
250
+ };
251
+ var handleTouchStart = function handleTouchStart(e) {
252
+ var _e$touches;
253
+ if ((_e$touches = e.touches) !== null && _e$touches !== void 0 && _e$touches.length) lastTouchYRef.current = e.touches[0].clientY;
254
+ };
255
+ var handleTouchMove = function handleTouchMove(e) {
256
+ var _e$touches2;
257
+ var current = containerRef.current;
258
+ if (!current || !((_e$touches2 = e.touches) !== null && _e$touches2 !== void 0 && _e$touches2.length)) return;
259
+ var y = e.touches[0].clientY;
260
+ var prev = lastTouchYRef.current;
261
+ lastTouchYRef.current = y;
262
+ if (prev === null) return;
263
+ var fingerDelta = y - prev;
264
+ if (fingerDelta <= 5) return;
265
+ if (current.scrollTop <= threshold) tryLoadMore();
266
+ };
267
+ container.addEventListener('scroll', handleScroll);
268
+ container.addEventListener('wheel', handleWheel, {
269
+ passive: true
270
+ });
271
+ container.addEventListener('touchstart', handleTouchStart, {
272
+ passive: true
273
+ });
274
+ container.addEventListener('touchmove', handleTouchMove, {
275
+ passive: true
276
+ });
277
+ return function () {
278
+ var _cancel, _ref3;
279
+ container.removeEventListener('scroll', handleScroll);
280
+ container.removeEventListener('wheel', handleWheel);
281
+ container.removeEventListener('touchstart', handleTouchStart);
282
+ container.removeEventListener('touchmove', handleTouchMove);
283
+ (_cancel = (_ref3 = handleScroll).cancel) === null || _cancel === void 0 || _cancel.call(_ref3);
284
+ };
285
+ }, [containerRef, loadMore]);
286
+ useEffect(function () {
287
+ if (historyScrollRef.current && containerRef.current && !isMoreLoading) {
288
+ var _historyScrollRef$cur = historyScrollRef.current,
289
+ height = _historyScrollRef$cur.height,
290
+ top = _historyScrollRef$cur.top;
291
+ var container = containerRef.current;
292
+ var newHeight = container.scrollHeight;
293
+ var heightDiff = newHeight - height;
294
+ if (heightDiff > 0) {
295
+ requestAnimationFrame(function () {
296
+ container.scrollTop = top + heightDiff;
297
+ });
298
+ }
299
+ historyScrollRef.current = null;
300
+ }
301
+ }, [messageList, isMoreLoading, containerRef]);
241
302
  return {
242
303
  getContentMessageList: getContentMessageList,
243
304
  isMoreLoading: isMoreLoading,
244
- hasMore: hasMore
305
+ hasMore: hasMore,
306
+ loadMore: loadMore
245
307
  };
246
308
  };
247
309
  export default useChatHistory;
@@ -32,6 +32,7 @@ declare const useCommonChatAPI: (props: IHookProps) => {
32
32
  handleInterrupt: () => Promise<void>;
33
33
  getContentMessageList: (pageIndex?: number, curPageSize?: number) => Promise<void>;
34
34
  hasMore: React.MutableRefObject<boolean>;
35
+ loadMore: () => void;
35
36
  handleSend: (val: string, agent?: any, isSystemAuto?: boolean, conversationId?: number) => Promise<void>;
36
37
  scrollBottomForce: (animate?: boolean | undefined) => void;
37
38
  showBackBottom: boolean;
@@ -648,7 +648,8 @@ var useCommonChatAPI = function useCommonChatAPI(props) {
648
648
  var _useChatHistory = useChatHistory(checkUnfinishedMessage, scrollBottomForce, containerRef),
649
649
  getContentMessageList = _useChatHistory.getContentMessageList,
650
650
  isMoreLoading = _useChatHistory.isMoreLoading,
651
- hasMore = _useChatHistory.hasMore;
651
+ hasMore = _useChatHistory.hasMore,
652
+ loadMore = _useChatHistory.loadMore;
652
653
  React.useEffect(function () {
653
654
  if (!isMoreLoading && messageList.length > 0) {
654
655
  if (messageList[messageList.length - 1].type === 1) {
@@ -958,6 +959,9 @@ var useCommonChatAPI = function useCommonChatAPI(props) {
958
959
  if (conversationId && conversationIdRef.current !== conversationId) {
959
960
  conversationIdRef.current = conversationId;
960
961
  // 清空当前会话的消息列表
962
+ dispatch(setMessageList({
963
+ messageList: []
964
+ }));
961
965
  messageListRef.current = [];
962
966
  // 如果有初始化发送值,不自动加载历史消息,而是直接发送初始化发送值
963
967
  if (autoLoadConversation && !autoSendValue) {
@@ -1299,6 +1303,7 @@ var useCommonChatAPI = function useCommonChatAPI(props) {
1299
1303
  handleInterrupt: handleInterrupt,
1300
1304
  getContentMessageList: getContentMessageList,
1301
1305
  hasMore: hasMore,
1306
+ loadMore: loadMore,
1302
1307
  handleSend: handleSend,
1303
1308
  scrollBottomForce: scrollBottomForce,
1304
1309
  showBackBottom: currentPosition > 100,
@@ -99,16 +99,21 @@ var useScroll = function useScroll(containerRef) {
99
99
  setCurrentPosition(position);
100
100
  }
101
101
  }, [containerRef.current]);
102
-
103
- // 滚轮事件处理 - 检测用户向上滚动意图
104
102
  var handleWheel = React.useCallback(throttle(function (e) {
105
- // 向上滚动时立即停止自动滚动
106
- if (e.deltaY < 0) {
103
+ var container = containerRef.current;
104
+ if (!container) return;
105
+ var scrollTop = container.scrollTop,
106
+ scrollHeight = container.scrollHeight,
107
+ clientHeight = container.clientHeight;
108
+ var canScroll = scrollHeight - clientHeight > 1;
109
+ if (!canScroll) return;
110
+ var position = Math.max(0, scrollHeight - clientHeight - scrollTop);
111
+ if (e.deltaY < -2) {
107
112
  markUserInteraction(true);
113
+ } else if (e.deltaY > 2 && position <= bottomPosition) {
114
+ markUserInteraction(false);
108
115
  }
109
- }, 100), [markUserInteraction]);
110
-
111
- // 滚动事件处理
116
+ }, 100), [containerRef.current, bottomPosition, markUserInteraction]);
112
117
  var handleScroll = React.useCallback(throttle(function () {
113
118
  if (!containerRef.current) return;
114
119
  var _containerRef$current2 = containerRef.current,
@@ -118,26 +123,20 @@ var useScroll = function useScroll(containerRef) {
118
123
  var position = Math.max(0, scrollHeight - clientHeight - scrollTop);
119
124
  setCurrentPosition(position);
120
125
  setIsScrolling(true);
121
-
122
- // 检测滚动方向
123
126
  var scrollDelta = scrollTop - refs.lastScrollTop;
124
127
  if (Math.abs(scrollDelta) > 2) {
125
128
  if (scrollDelta < 0) {
126
- // 向上滚动:用户可能在看历史消息
127
129
  markUserInteraction(true);
128
- } else if (position <= 5) {
129
- // 向下滚动到底部:恢复自动滚动
130
+ } else if (scrollDelta > 0 && position <= bottomPosition) {
130
131
  markUserInteraction(false);
131
132
  }
132
133
  refs.lastScrollTop = scrollTop;
133
134
  }
134
-
135
- // 设置滚动结束状态
136
135
  if (refs.scrollTimeout) clearTimeout(refs.scrollTimeout);
137
136
  refs.scrollTimeout = setTimeout(function () {
138
137
  setIsScrolling(false);
139
138
  }, 200);
140
- }, 150), [containerRef.current, markUserInteraction]);
139
+ }, 150), [containerRef.current, bottomPosition, markUserInteraction]);
141
140
 
142
141
  // 事件监听器
143
142
  React.useEffect(function () {
@@ -0,0 +1,13 @@
1
+ declare module 'react-virtuoso' {
2
+ import * as React from 'react';
3
+
4
+ export interface VirtuosoProps<TData = any> extends React.HTMLAttributes<HTMLDivElement> {
5
+ data?: TData[];
6
+ customScrollParent?: HTMLElement | null;
7
+ itemContent?: (index: number, data: TData) => React.ReactNode;
8
+ startReached?: () => void;
9
+ style?: React.CSSProperties;
10
+ }
11
+
12
+ export const Virtuoso: React.ComponentType<VirtuosoProps<any>>;
13
+ }