@myun/gimi-chat 0.7.3 → 0.7.5

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.
@@ -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,
@@ -5,6 +5,7 @@
5
5
  display: flex;
6
6
  gap: 20px;
7
7
  position: relative;
8
+ overflow-x: hidden;
8
9
  }
9
10
 
10
11
  .chat_content {
@@ -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() {
@@ -137,6 +104,7 @@ var useChatHistory = function useChatHistory(checkUnfinishedMessage, scrollBotto
137
104
  newChatList,
138
105
  lastUserRequestMessage,
139
106
  lastMessage,
107
+ waitForStableHeight,
140
108
  _lastUserRequestMessa,
141
109
  container,
142
110
  _args = arguments;
@@ -158,13 +126,14 @@ var useChatHistory = function useChatHistory(checkUnfinishedMessage, scrollBotto
158
126
  botId: currentAgentObj === null || currentAgentObj === void 0 ? void 0 : currentAgentObj.botId
159
127
  }, currentBusinessParams)
160
128
  };
129
+ isMoreLoadingRef.current = true;
161
130
  setIsMoreLoading(true);
162
- _context.next = 10;
131
+ _context.next = 11;
163
132
  return getMessageList(params);
164
- case 10:
133
+ case 11:
165
134
  res = _context.sent;
166
135
  if (!(res && res.status === 0)) {
167
- _context.next = 36;
136
+ _context.next = 38;
168
137
  break;
169
138
  }
170
139
  resData = formatFields(res.result.data, res.result.first ? [] : currentMessageList) || [];
@@ -179,21 +148,53 @@ var useChatHistory = function useChatHistory(checkUnfinishedMessage, scrollBotto
179
148
  }
180
149
  hasMore.current = res.result.last === undefined ? false : !res.result.last;
181
150
  if (!res.result.first) {
182
- _context.next = 26;
151
+ _context.next = 28;
183
152
  break;
184
153
  }
185
154
  dispatch(setMessageList({
186
155
  messageList: _newResData
187
156
  }));
188
- _context.next = 23;
157
+ _context.next = 24;
189
158
  return checkUnfinishedMessage(_newResData);
190
- case 23:
191
- setTimeout(function () {
192
- scrollBottomForce();
193
- }, 0);
194
- _context.next = 34;
159
+ case 24:
160
+ // 3. 滚动到底部:待稳定高度后再滚动
161
+ waitForStableHeight = function waitForStableHeight() {
162
+ var maxFrames = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 32;
163
+ var lastHeight = -1;
164
+ var stableFrames = 0;
165
+ var frames = 0;
166
+ return new Promise(function (resolve) {
167
+ var tick = function tick() {
168
+ var container = containerRef.current;
169
+ if (!container) {
170
+ resolve();
171
+ return;
172
+ }
173
+ var h = container.scrollHeight;
174
+ if (h === lastHeight) {
175
+ stableFrames += 1;
176
+ } else {
177
+ stableFrames = 0;
178
+ lastHeight = h;
179
+ }
180
+ frames += 1;
181
+ if (stableFrames >= 2 || frames >= maxFrames) {
182
+ resolve();
183
+ return;
184
+ }
185
+ requestAnimationFrame(tick);
186
+ };
187
+ requestAnimationFrame(tick);
188
+ });
189
+ };
190
+ requestAnimationFrame(function () {
191
+ waitForStableHeight().then(function () {
192
+ scrollBottomForce(false);
193
+ });
194
+ });
195
+ _context.next = 36;
195
196
  break;
196
- case 26:
197
+ case 28:
197
198
  container = containerRef.current;
198
199
  if (container) {
199
200
  historyScrollRef.current = {
@@ -205,43 +206,134 @@ var useChatHistory = function useChatHistory(checkUnfinishedMessage, scrollBotto
205
206
  // 2. 更新数据
206
207
  // 判断是否需要重写推荐列表
207
208
  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;
209
+ _context.next = 35;
209
210
  break;
210
211
  }
211
- _context.next = 31;
212
+ _context.next = 33;
212
213
  return rewriteRecommendListFormHistory(newChatList, lastUserRequestMessage.chatId);
213
- case 31:
214
- _context.next = 34;
215
- break;
216
214
  case 33:
215
+ _context.next = 36;
216
+ break;
217
+ case 35:
217
218
  dispatch(setMessageList({
218
219
  messageList: newChatList
219
220
  }));
220
- case 34:
221
- _context.next = 37;
222
- break;
223
221
  case 36:
222
+ _context.next = 39;
223
+ break;
224
+ case 38:
224
225
  if (res.status === 1034) {
225
226
  Toast.error(res.message || '获取历史记录失败');
226
227
  }
227
- case 37:
228
+ case 39:
229
+ isMoreLoadingRef.current = false;
228
230
  setIsMoreLoading(false);
229
- _context.next = 43;
231
+ _context.next = 48;
230
232
  break;
231
- case 40:
232
- _context.prev = 40;
233
+ case 43:
234
+ _context.prev = 43;
233
235
  _context.t0 = _context["catch"](5);
234
236
  console.error(_context.t0);
235
- case 43:
237
+ isMoreLoadingRef.current = false;
238
+ setIsMoreLoading(false);
239
+ case 48:
236
240
  case "end":
237
241
  return _context.stop();
238
242
  }
239
- }, _callee, null, [[5, 40]]);
240
- })), []);
243
+ }, _callee, null, [[5, 43]]);
244
+ })), [checkUnfinishedMessage, containerRef, dispatch, getMessageList, param.pageIndex, param.pageSize, rewriteRecommendListFormHistory, scrollBottomForce]);
245
+ var loadMore = useCallback(function () {
246
+ if (!hasMore.current || isMoreLoadingRef.current || isMsgRecievingRef.current || !conversationIdRef.current) {
247
+ return;
248
+ }
249
+ isMoreLoadingRef.current = true;
250
+ setIsMoreLoading(true);
251
+ setParam(function (prev) {
252
+ var newPageIndex = prev.pageIndex + 1;
253
+ getContentMessageList(newPageIndex, prev.pageSize);
254
+ return _objectSpread(_objectSpread({}, prev), {}, {
255
+ pageIndex: newPageIndex
256
+ });
257
+ });
258
+ }, [getContentMessageList]);
259
+ useEffect(function () {
260
+ var container = containerRef.current;
261
+ if (!container) return;
262
+ var threshold = 40;
263
+ var cooldownMs = 250;
264
+ var tryLoadMore = function tryLoadMore() {
265
+ var now = Date.now();
266
+ if (now - lastLoadMoreAtRef.current < cooldownMs) return;
267
+ lastLoadMoreAtRef.current = now;
268
+ loadMore();
269
+ };
270
+ var handleScroll = throttle(function () {
271
+ if (!containerRef.current) return;
272
+ var scrollTop = containerRef.current.scrollTop;
273
+ if (scrollTop <= threshold) tryLoadMore();
274
+ }, 120);
275
+ var handleWheel = function handleWheel(e) {
276
+ var current = containerRef.current;
277
+ if (!current) return;
278
+ if (e.deltaY >= -5) return;
279
+ if (current.scrollTop <= threshold) tryLoadMore();
280
+ };
281
+ var handleTouchStart = function handleTouchStart(e) {
282
+ var _e$touches;
283
+ if ((_e$touches = e.touches) !== null && _e$touches !== void 0 && _e$touches.length) lastTouchYRef.current = e.touches[0].clientY;
284
+ };
285
+ var handleTouchMove = function handleTouchMove(e) {
286
+ var _e$touches2;
287
+ var current = containerRef.current;
288
+ if (!current || !((_e$touches2 = e.touches) !== null && _e$touches2 !== void 0 && _e$touches2.length)) return;
289
+ var y = e.touches[0].clientY;
290
+ var prev = lastTouchYRef.current;
291
+ lastTouchYRef.current = y;
292
+ if (prev === null) return;
293
+ var fingerDelta = y - prev;
294
+ if (fingerDelta <= 5) return;
295
+ if (current.scrollTop <= threshold) tryLoadMore();
296
+ };
297
+ container.addEventListener('scroll', handleScroll);
298
+ container.addEventListener('wheel', handleWheel, {
299
+ passive: true
300
+ });
301
+ container.addEventListener('touchstart', handleTouchStart, {
302
+ passive: true
303
+ });
304
+ container.addEventListener('touchmove', handleTouchMove, {
305
+ passive: true
306
+ });
307
+ return function () {
308
+ var _cancel, _ref3;
309
+ container.removeEventListener('scroll', handleScroll);
310
+ container.removeEventListener('wheel', handleWheel);
311
+ container.removeEventListener('touchstart', handleTouchStart);
312
+ container.removeEventListener('touchmove', handleTouchMove);
313
+ (_cancel = (_ref3 = handleScroll).cancel) === null || _cancel === void 0 || _cancel.call(_ref3);
314
+ };
315
+ }, [containerRef, loadMore]);
316
+ useEffect(function () {
317
+ if (historyScrollRef.current && containerRef.current && !isMoreLoading) {
318
+ var _historyScrollRef$cur = historyScrollRef.current,
319
+ height = _historyScrollRef$cur.height,
320
+ top = _historyScrollRef$cur.top;
321
+ var container = containerRef.current;
322
+ var newHeight = container.scrollHeight;
323
+ var heightDiff = newHeight - height;
324
+ if (heightDiff > 0) {
325
+ requestAnimationFrame(function () {
326
+ container.scrollTop = top + heightDiff;
327
+ });
328
+ }
329
+ historyScrollRef.current = null;
330
+ }
331
+ }, [messageList, isMoreLoading, containerRef]);
241
332
  return {
242
333
  getContentMessageList: getContentMessageList,
243
334
  isMoreLoading: isMoreLoading,
244
- hasMore: hasMore
335
+ hasMore: hasMore,
336
+ loadMore: loadMore
245
337
  };
246
338
  };
247
339
  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,