bhd-components 0.10.7 → 0.10.8

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.
@@ -30,6 +30,8 @@ const Footer = /*#__PURE__*/ forwardRef((props, ref)=>{
30
30
  if (fileUpload) {
31
31
  fileUpload = _object_spread({}, defaultFileUploadProps, fileUpload);
32
32
  }
33
+ const footerDomRef = useRef(null);
34
+ const resizeObserverRef = useRef(null);
33
35
  const fileListRef = useRef(null);
34
36
  const ctrl = useRef(); //停止生成ai回答时使用
35
37
  const [textValue, setTextValue] = useState("");
@@ -72,7 +74,9 @@ const Footer = /*#__PURE__*/ forwardRef((props, ref)=>{
72
74
  }, fileListRef.current);
73
75
  });
74
76
  useEffect(()=>{
77
+ listenerFooterHeight();
75
78
  return ()=>{
79
+ resizeObserverRef.current && resizeObserverRef.current.disconnect();
76
80
  clearTimeout(updateMsgRef.current);
77
81
  };
78
82
  }, []);
@@ -85,6 +89,16 @@ const Footer = /*#__PURE__*/ forwardRef((props, ref)=>{
85
89
  referencesSource,
86
90
  sending
87
91
  ]);
92
+ // 监听footer变化
93
+ const listenerFooterHeight = ()=>{
94
+ if (!footerDomRef.current) return;
95
+ // 创建ResizeObserver实例
96
+ resizeObserverRef.current = new ResizeObserver((entries)=>{
97
+ apiRef.contentApi && apiRef.contentApi.scrollToBottom();
98
+ });
99
+ // 开始观察footer元素
100
+ resizeObserverRef.current.observe(footerDomRef.current);
101
+ };
88
102
  // 是否允许发送消息
89
103
  const canSendMsg = useMemo(()=>{
90
104
  if (textValue.trim().length === 0) return false;
@@ -186,7 +200,8 @@ const Footer = /*#__PURE__*/ forwardRef((props, ref)=>{
186
200
  content: value,
187
201
  location: "right",
188
202
  reference: recordRef.current.referencesSource,
189
- source: null
203
+ source: null,
204
+ fileList: fileListRef.current.getFileList()
190
205
  });
191
206
  sendMsgAjax();
192
207
  };
@@ -203,7 +218,8 @@ const Footer = /*#__PURE__*/ forwardRef((props, ref)=>{
203
218
  content: "正在输入...",
204
219
  location: "left",
205
220
  reference: null,
206
- source: null
221
+ source: null,
222
+ fileList: fileListRef.current.getFileList()
207
223
  });
208
224
  let msgContent = "";
209
225
  setSending(true);
@@ -226,6 +242,7 @@ const Footer = /*#__PURE__*/ forwardRef((props, ref)=>{
226
242
  setSending(false);
227
243
  if (recordMsgObj.id) {
228
244
  apiRef.contentApi.recordMsg(recordMsgObj);
245
+ apiRef.contentApi.setSendingId(recordMsgObj.id);
229
246
  }
230
247
  console.log("onclose: ", recordMsgObj);
231
248
  };
@@ -254,11 +271,12 @@ const Footer = /*#__PURE__*/ forwardRef((props, ref)=>{
254
271
  delete data.content;
255
272
  recordMsgObj = _object_spread({
256
273
  createTime: createTime,
257
- content: msgContent,
274
+ content: msgContent || "正在输入...",
258
275
  location: "left",
259
276
  reference: null,
260
277
  source: null
261
278
  }, data);
279
+ apiRef.contentApi.setSendingId(data.id);
262
280
  apiRef.contentApi.updateMsg(msgId, recordMsgObj);
263
281
  msgId = data.id;
264
282
  updateMsgRef.current = setTimeout(function() {
@@ -292,6 +310,7 @@ const Footer = /*#__PURE__*/ forwardRef((props, ref)=>{
292
310
  };
293
311
  return /*#__PURE__*/ _jsx("div", {
294
312
  className: `${getCls("footer")} ${className}`,
313
+ ref: footerDomRef,
295
314
  children: /*#__PURE__*/ _jsxs("div", {
296
315
  className: `${getCls("footerBody")} ${judegTextLengthWarn() ? getCls("footerBodyWarn") : ""}`,
297
316
  children: [
@@ -32,11 +32,26 @@ const ReferencesIcon = (props)=>{
32
32
  console.log("apiRef", apiRef);
33
33
  if (apiRef && apiRef.footerApi) {
34
34
  console.log("itemitem", item);
35
- apiRef.footerApi.setReferences({
36
- type: "text",
37
- value: item.content,
38
- source: item
39
- });
35
+ if (item.type === "file") {
36
+ apiRef.footerApi.setReferences({
37
+ type: "file",
38
+ value: {
39
+ name: item.fileTitle,
40
+ suffix: item.suffix,
41
+ fileId: item.id,
42
+ url: "",
43
+ status: "success",
44
+ source: null
45
+ },
46
+ source: item
47
+ });
48
+ } else {
49
+ apiRef.footerApi.setReferences({
50
+ type: "text",
51
+ value: item.content,
52
+ source: item
53
+ });
54
+ }
40
55
  }
41
56
  };
42
57
  return /*#__PURE__*/ _jsx("div", {
@@ -13,6 +13,7 @@ import CopyIcon from "../copyIcon";
13
13
  import ReferencesIcon from "../referencesIcon";
14
14
  import { UpVoteBtn, DownVoteBtn } from "../remarkBtn";
15
15
  import RefreshBtn from "../refreshBtn";
16
+ import { fileIconRender } from "../fileList/fileIcon";
16
17
  const Header = ({ context })=>{
17
18
  const { prefix, loading } = context;
18
19
  if (!loading) return null;
@@ -45,13 +46,14 @@ const VirtuosoList = /*#__PURE__*/ forwardRef((props, ref)=>{
45
46
  const { getList, coverRenderText, msgAction = [
46
47
  "copy",
47
48
  "references"
48
- ], coverRenderReferences, onRecordMessage = ()=>{}, onVoteChange = ()=>{}, onRefresh = ()=>{} } = contentConfig;
49
+ ], coverRenderReferences, onRecordMessage = ()=>{}, onVoteChange = ()=>{}, onRefresh = ()=>{}, iconFileRender } = contentConfig;
49
50
  const loadMoreProps = contentConfig.loadMore || true;
50
51
  const virtuosoRef = useRef(null);
51
52
  const [loading, setLoading] = useState(false); // 是否加载中
52
53
  const [dataSource, setDataSource] = useState([]);
53
54
  const [firstItemIndex, setFirstItemIndex] = useState(0);
54
55
  const [page, setPage] = useState(1);
56
+ const [sendingId, setSendingId] = useState("");
55
57
  const [pageSize, setPageSize] = useState(contentConfig.pageSize || 30);
56
58
  const [total, setTotal] = useState(0);
57
59
  const timerRef = useRef({
@@ -64,7 +66,8 @@ const VirtuosoList = /*#__PURE__*/ forwardRef((props, ref)=>{
64
66
  pageSize: pageSize,
65
67
  total: total,
66
68
  dataSource: dataSource,
67
- maxPage: Math.ceil(total / pageSize)
69
+ maxPage: Math.ceil(total / pageSize),
70
+ sendingId: ""
68
71
  });
69
72
  const timeRenderCache = useRef(new Map()).current;
70
73
  const htmlRenderCache = useRef(new Map()).current;
@@ -81,6 +84,9 @@ const VirtuosoList = /*#__PURE__*/ forwardRef((props, ref)=>{
81
84
  msg
82
85
  ];
83
86
  });
87
+ timerRef.current.scrollTimer = setTimeout(()=>{
88
+ scrollToBottom();
89
+ }, 100);
84
90
  },
85
91
  updateMsg: (id, obj)=>{
86
92
  setDataSource((data)=>{
@@ -116,12 +122,9 @@ const VirtuosoList = /*#__PURE__*/ forwardRef((props, ref)=>{
116
122
  changeDataSource: (data)=>{
117
123
  setDataSource(data);
118
124
  },
119
- scrollToBottom: function() {
120
- if (!virtuosoRef.current) return;
121
- virtuosoRef.current.scrollToIndex({
122
- index: "LAST",
123
- behavior: "auto"
124
- });
125
+ scrollToBottom,
126
+ setSendingId: (id)=>{
127
+ setSendingId(id);
125
128
  }
126
129
  };
127
130
  });
@@ -159,12 +162,21 @@ const VirtuosoList = /*#__PURE__*/ forwardRef((props, ref)=>{
159
162
  recordRef.current.total = total;
160
163
  recordRef.current.dataSource = dataSource;
161
164
  recordRef.current.maxPage = Math.ceil(total / pageSize);
165
+ recordRef.current.sendingId = sendingId;
162
166
  }, [
163
167
  page,
164
168
  pageSize,
165
169
  total,
166
- dataSource
170
+ dataSource,
171
+ sendingId
167
172
  ]);
173
+ const scrollToBottom = ()=>{
174
+ if (!virtuosoRef.current) return;
175
+ virtuosoRef.current.scrollToIndex({
176
+ index: "LAST",
177
+ behavior: "auto"
178
+ });
179
+ };
168
180
  const getData = (page, pageSize)=>{
169
181
  setLoading(true);
170
182
  clearTimeout(timerRef.current.loadMore);
@@ -199,18 +211,7 @@ const VirtuosoList = /*#__PURE__*/ forwardRef((props, ref)=>{
199
211
  ]);
200
212
  const itemContent = (index, item)=>{
201
213
  const timeNode = renderTime(item);
202
- let cahceKey = item.id + "-" + item.content;
203
214
  let contentNode = null;
204
- // if (htmlRenderCache.has(cahceKey)) {
205
- // contentNode = htmlRenderCache.get(cahceKey);
206
- // } else {
207
- // const html = markToHtml(item.content, item.id);
208
- // contentNode = <div dangerouslySetInnerHTML={{ __html: html }}></div>;
209
- // if (coverRenderText) {
210
- // contentNode = coverRenderText(item, html);
211
- // }
212
- // htmlRenderCache.set(cahceKey, contentNode);
213
- // }
214
215
  const html = markToHtml(item.content, item.id);
215
216
  contentNode = /*#__PURE__*/ _jsx("div", {
216
217
  dangerouslySetInnerHTML: {
@@ -220,6 +221,32 @@ const VirtuosoList = /*#__PURE__*/ forwardRef((props, ref)=>{
220
221
  if (coverRenderText) {
221
222
  contentNode = coverRenderText(item, html);
222
223
  }
224
+ // item.type = "file";
225
+ // item.suffix = "docx";
226
+ // item.fileTitle = "这是一个文件名称.docx";
227
+ // item.fileSize = "5Mb";
228
+ if (item.type === "file") {
229
+ contentNode = /*#__PURE__*/ _jsxs("div", {
230
+ className: `${getCls("msgItem-file")}`,
231
+ children: [
232
+ /*#__PURE__*/ _jsx("div", {
233
+ className: `${getCls("msgItem-file-left")}`,
234
+ children: fileIconRender(item.suffix, iconFileRender)
235
+ }),
236
+ /*#__PURE__*/ _jsxs("div", {
237
+ className: `${getCls("msgItem-file-right")}`,
238
+ children: [
239
+ /*#__PURE__*/ _jsx("p", {
240
+ children: item.fileTitle
241
+ }),
242
+ /*#__PURE__*/ _jsx("p", {
243
+ children: item.fileSize
244
+ })
245
+ ]
246
+ })
247
+ ]
248
+ });
249
+ }
223
250
  // 是否显示时间
224
251
  let itemNode = /*#__PURE__*/ _jsx("div", {
225
252
  className: `${getCls("msgItem")} ${item.location === "left" ? getCls("msgItem-left") : getCls("msgItem-right")}`,
@@ -315,6 +342,7 @@ const VirtuosoList = /*#__PURE__*/ forwardRef((props, ref)=>{
315
342
  topDom.style.cssText = "";
316
343
  };
317
344
  const renderAction = (location, item)=>{
345
+ if (item.id === "inputing" || item.id === "helloMsg" || item.id === recordRef.current.sendingId) return null;
318
346
  let copyNode = /*#__PURE__*/ _jsx(CopyIcon, {
319
347
  prefix: prefix,
320
348
  content: item.content
@@ -328,6 +356,7 @@ const VirtuosoList = /*#__PURE__*/ forwardRef((props, ref)=>{
328
356
  prefix: prefix,
329
357
  isActive: item.vote === "up",
330
358
  clickFn: ()=>{
359
+ onVoteChange(item.vote === "up" ? "" : "up", item);
331
360
  setDataSource((data)=>{
332
361
  return data.map((ite)=>{
333
362
  if (item.id === ite.id) {
@@ -336,13 +365,13 @@ const VirtuosoList = /*#__PURE__*/ forwardRef((props, ref)=>{
336
365
  return ite;
337
366
  });
338
367
  });
339
- onVoteChange(item.vote === "up" ? "" : "up", item);
340
368
  }
341
369
  });
342
370
  let DownVoteNode = /*#__PURE__*/ _jsx(DownVoteBtn, {
343
371
  prefix: prefix,
344
372
  isActive: item.vote === "down",
345
373
  clickFn: ()=>{
374
+ onVoteChange(item.vote === "down" ? "" : "down", item);
346
375
  setDataSource((data)=>{
347
376
  return data.map((ite)=>{
348
377
  if (item.id === ite.id) {
@@ -351,7 +380,6 @@ const VirtuosoList = /*#__PURE__*/ forwardRef((props, ref)=>{
351
380
  return ite;
352
381
  });
353
382
  });
354
- onVoteChange(item.vote === "down" ? "" : "down", item);
355
383
  }
356
384
  });
357
385
  let RefreshNode = /*#__PURE__*/ _jsx(RefreshBtn, {
@@ -362,6 +390,12 @@ const VirtuosoList = /*#__PURE__*/ forwardRef((props, ref)=>{
362
390
  UpVoteNode = null;
363
391
  DownVoteNode = null;
364
392
  }
393
+ if (item.type === "file") {
394
+ copyNode = null;
395
+ UpVoteNode = null;
396
+ DownVoteNode = null;
397
+ RefreshNode = null;
398
+ }
365
399
  let leftNodes = null;
366
400
  let rightNodes = /*#__PURE__*/ _jsxs(_Fragment, {
367
401
  children: [
@@ -71,11 +71,11 @@
71
71
  text-align: right;
72
72
  height: 37px;
73
73
  line-height: 37px;
74
- padding: 0 ;
75
- padding-right: 16px ;
74
+ padding: 0;
75
+ padding-right: 16px;
76
76
  position: relative;
77
77
  cursor: pointer;
78
- font-weight: 400 ;
78
+ font-weight: 400;
79
79
  top: 6px;
80
80
  &.copyCodeFun {
81
81
  display: flex;
@@ -266,6 +266,41 @@
266
266
  border-radius: 0 0 4px 4px;
267
267
  }
268
268
  }
269
+ .msgItem-file {
270
+ display: flex;
271
+ align-items: center;
272
+ padding: 8px 12px;
273
+ background: #fafafa;
274
+ border-radius: 8px;
275
+ border: 1px solid #ebebeb;
276
+ gap: 12px;
277
+ .msgItem-file-left{
278
+ font-size: 24px;
279
+ display: flex;
280
+ justify-content: center;
281
+ align-items: center;
282
+ padding: 0;
283
+ margin: 0;
284
+ &>i{
285
+ display: flex;
286
+ font-size: 24px;
287
+ }
288
+ }
289
+ .msgItem-file-right{
290
+ font-size: 14px;
291
+ font-weight: 400;
292
+ color: rgba(0, 0, 0, 0.65);
293
+ &>p{
294
+ &:nth-child(1){
295
+ margin-bottom: 4px;
296
+ }
297
+ &:nth-child(2){
298
+ font-size: 12px;
299
+ color: rgba(0, 0, 0, 0.25);
300
+ }
301
+ }
302
+ }
303
+ }
269
304
  }
270
305
  .msgItem-action {
271
306
  border-top: 1px solid rgba(0, 0, 0, 0.06);
@@ -62,6 +62,7 @@ export interface contentConfigProps {
62
62
  onRecordMessage?: (item: dataItemType) => void; // 发送和接收的消息记录
63
63
  onVoteChange?: (type:string,item: dataItemType) => void; // 点赞 或踩
64
64
  onRefresh?: (item:dataItemType) => void;// 刷新
65
+ iconFileRender?: (suffix: string) => React.ReactNode; // 文件上传的 icon。参数 文件对象file 返回值为图标
65
66
  }
66
67
 
67
68
  // content props
@@ -271,6 +272,7 @@ export interface VirtuosoListRefProps {
271
272
  upateDataSource:(id:string,obj:dataItemType)=>void;
272
273
  changeDataSource:(list:dataItemType[])=>void;
273
274
  scrollToBottom: () => void;
275
+ setSendingId:(id:string)=>void;
274
276
  }
275
277
 
276
278
  export interface contentRefProps extends VirtuosoListRefProps {}
@@ -290,4 +292,9 @@ export interface dataItemType {
290
292
  reference: referenceType | null; // 引用数据
291
293
  source: any; //原消息对象
292
294
  vote?:string;// "up":点赞。"down":踩
295
+ type?:"file"|"text",
296
+ suffix?:string;
297
+ fileSize?:string;
298
+ fileTitle?:string;
299
+ fileList?:fileCustomProps[];
293
300
  }
@@ -32,6 +32,8 @@ var Footer = /*#__PURE__*/ forwardRef(function(props, ref) {
32
32
  if (fileUpload) {
33
33
  fileUpload = _object_spread({}, defaultFileUploadProps, fileUpload);
34
34
  }
35
+ var footerDomRef = useRef(null);
36
+ var resizeObserverRef = useRef(null);
35
37
  var fileListRef = useRef(null);
36
38
  var ctrl = useRef(); //停止生成ai回答时使用
37
39
  var _useState = _sliced_to_array(useState(""), 2), textValue = _useState[0], setTextValue = _useState[1];
@@ -74,7 +76,9 @@ var Footer = /*#__PURE__*/ forwardRef(function(props, ref) {
74
76
  }, fileListRef.current);
75
77
  });
76
78
  useEffect(function() {
79
+ listenerFooterHeight();
77
80
  return function() {
81
+ resizeObserverRef.current && resizeObserverRef.current.disconnect();
78
82
  clearTimeout(updateMsgRef.current);
79
83
  };
80
84
  }, []);
@@ -87,6 +91,16 @@ var Footer = /*#__PURE__*/ forwardRef(function(props, ref) {
87
91
  referencesSource,
88
92
  sending
89
93
  ]);
94
+ // 监听footer变化
95
+ var listenerFooterHeight = function() {
96
+ if (!footerDomRef.current) return;
97
+ // 创建ResizeObserver实例
98
+ resizeObserverRef.current = new ResizeObserver(function(entries) {
99
+ apiRef.contentApi && apiRef.contentApi.scrollToBottom();
100
+ });
101
+ // 开始观察footer元素
102
+ resizeObserverRef.current.observe(footerDomRef.current);
103
+ };
90
104
  // 是否允许发送消息
91
105
  var canSendMsg = useMemo(function() {
92
106
  if (textValue.trim().length === 0) return false;
@@ -188,7 +202,8 @@ var Footer = /*#__PURE__*/ forwardRef(function(props, ref) {
188
202
  content: value,
189
203
  location: "right",
190
204
  reference: recordRef.current.referencesSource,
191
- source: null
205
+ source: null,
206
+ fileList: fileListRef.current.getFileList()
192
207
  });
193
208
  sendMsgAjax();
194
209
  };
@@ -213,7 +228,8 @@ var Footer = /*#__PURE__*/ forwardRef(function(props, ref) {
213
228
  content: "正在输入...",
214
229
  location: "left",
215
230
  reference: null,
216
- source: null
231
+ source: null,
232
+ fileList: fileListRef.current.getFileList()
217
233
  });
218
234
  var msgContent = "";
219
235
  setSending(true);
@@ -236,6 +252,7 @@ var Footer = /*#__PURE__*/ forwardRef(function(props, ref) {
236
252
  setSending(false);
237
253
  if (recordMsgObj.id) {
238
254
  apiRef.contentApi.recordMsg(recordMsgObj);
255
+ apiRef.contentApi.setSendingId(recordMsgObj.id);
239
256
  }
240
257
  console.log("onclose: ", recordMsgObj);
241
258
  };
@@ -266,11 +283,12 @@ var Footer = /*#__PURE__*/ forwardRef(function(props, ref) {
266
283
  delete data.content;
267
284
  recordMsgObj = _object_spread({
268
285
  createTime: createTime,
269
- content: msgContent,
286
+ content: msgContent || "正在输入...",
270
287
  location: "left",
271
288
  reference: null,
272
289
  source: null
273
290
  }, data);
291
+ apiRef.contentApi.setSendingId(data.id);
274
292
  apiRef.contentApi.updateMsg(msgId, recordMsgObj);
275
293
  msgId = data.id;
276
294
  updateMsgRef.current = setTimeout(function() {
@@ -304,6 +322,7 @@ var Footer = /*#__PURE__*/ forwardRef(function(props, ref) {
304
322
  };
305
323
  return /*#__PURE__*/ _jsx("div", {
306
324
  className: "".concat(getCls("footer"), " ").concat(className),
325
+ ref: footerDomRef,
307
326
  children: /*#__PURE__*/ _jsxs("div", {
308
327
  className: "".concat(getCls("footerBody"), " ").concat(judegTextLengthWarn() ? getCls("footerBodyWarn") : ""),
309
328
  children: [
@@ -32,11 +32,26 @@ var ReferencesIcon = function(props) {
32
32
  console.log("apiRef", apiRef);
33
33
  if (apiRef && apiRef.footerApi) {
34
34
  console.log("itemitem", item);
35
- apiRef.footerApi.setReferences({
36
- type: "text",
37
- value: item.content,
38
- source: item
39
- });
35
+ if (item.type === "file") {
36
+ apiRef.footerApi.setReferences({
37
+ type: "file",
38
+ value: {
39
+ name: item.fileTitle,
40
+ suffix: item.suffix,
41
+ fileId: item.id,
42
+ url: "",
43
+ status: "success",
44
+ source: null
45
+ },
46
+ source: item
47
+ });
48
+ } else {
49
+ apiRef.footerApi.setReferences({
50
+ type: "text",
51
+ value: item.content,
52
+ source: item
53
+ });
54
+ }
40
55
  }
41
56
  };
42
57
  return /*#__PURE__*/ _jsx("div", {