yt-chat-components 1.5.4 → 1.5.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yt-chat-components",
3
- "version": "1.5.4",
3
+ "version": "1.5.5",
4
4
  "main": "build/static/js/bundle.min.js",
5
5
  "module": "build/static/js/bundle.min.js",
6
6
  "types": "build/static/js/index.d.ts",
@@ -23,6 +23,7 @@ import ChatMessagePlaceholder, {ChatMessagePlaceholderInThought} from "../chatPl
23
23
  import {UrlCard} from "./urlCard"
24
24
  import {CustomThoughtChainItem, CustomThoughtChainProps} from "./CustomThoughtChain";
25
25
  import CustomThoughtChain from "./CustomThoughtChain";
26
+ import {isFunction} from "lodash";
26
27
  let speechSynth = window.speechSynthesis;
27
28
  let utterance = null;
28
29
 
@@ -60,7 +61,8 @@ export default function ChatMessage({
60
61
  handleSendMessage,
61
62
  isLatest,
62
63
  key,
63
- isShowReadIcon
64
+ isShowReadIcon,
65
+ renderInitNode,
64
66
  }: ChatMessageType) {
65
67
  const parseFileName = (
66
68
  text: string,
@@ -167,6 +169,16 @@ export default function ChatMessage({
167
169
  }
168
170
  }
169
171
 
172
+ const getMessageClassSuffix = () => {
173
+ if (isFunction(renderInitNode)) {
174
+ return 'cl-justify-init'
175
+ }
176
+ if (isSend) {
177
+ return 'cl-justify-end';
178
+ }
179
+ return 'cl-justify-start';
180
+ }
181
+
170
182
  const renderUserMessage = () => {
171
183
  return (
172
184
  <div key={key} style={user_message_style} className="msg_userMessageBox">
@@ -224,6 +236,10 @@ export default function ChatMessage({
224
236
  )
225
237
  }
226
238
 
239
+ const renderInitMessage = () => {
240
+ return renderInitNode()
241
+ }
242
+
227
243
  const renderErrorMessage = () => {
228
244
  return (
229
245
  <div key={key} style={error_message_style} className={'cl-error_message'}>
@@ -668,6 +684,9 @@ export default function ChatMessage({
668
684
  // }
669
685
 
670
686
  const render = () => {
687
+ if (isFunction(renderInitNode)) {
688
+ return renderInitMessage()
689
+ }
671
690
  if (isSend){
672
691
  return renderUserMessage()
673
692
  }else {
@@ -680,7 +699,7 @@ export default function ChatMessage({
680
699
  }
681
700
 
682
701
  return (
683
- <div className={'cl-chat-message ' + (isSend ? ' cl-justify-end' : ' cl-justify-start')}>
702
+ <div className={'cl-chat-message ' + getMessageClassSuffix()}>
684
703
  {
685
704
  render()
686
705
  }
@@ -28,6 +28,7 @@ import {Image, message as messageTip, Tooltip, Typography} from 'antd';
28
28
  import {isEmpty, isFunction} from 'lodash';
29
29
  import btn_answer from '../../../assets/aicenter/btn_answer.png';
30
30
  import {MethodContext} from "../../previewDialogV2";
31
+ import TabSelector from "../../components/TabSelector";
31
32
 
32
33
 
33
34
  let mediaRecorder = null; // 语音对象,用于录音
@@ -89,6 +90,8 @@ export default function ChatWindow({
89
90
  isShowReadIcon,
90
91
  renderCustomDropDown,
91
92
  isTagsHidden,
93
+ isEnableForV1,
94
+ questions,
92
95
  }: {
93
96
  is_enable_call:boolean;
94
97
  tags: [];
@@ -138,6 +141,8 @@ export default function ChatWindow({
138
141
  isShowReadIcon?:boolean;
139
142
  renderCustomDropDown?: Function;
140
143
  isTagsHidden?: boolean;
144
+ isEnableForV1?: boolean;
145
+ questions?: any[];
141
146
  }) {
142
147
  const ref = useRef<HTMLDivElement>(null);
143
148
  const lastMessage = useRef<HTMLDivElement>(null);
@@ -949,7 +954,30 @@ export default function ChatWindow({
949
954
 
950
955
  finalChatHistoryList.forEach((item) => {
951
956
  addMessage(item)
952
- })
957
+ });
958
+ if (!isEnableForV1 && !isEmpty(questions)) {
959
+ addMessage({
960
+ messageItemList: [],
961
+ renderInitNode: () => <div style={{minHeight: '365px', width: '100%'}}>
962
+ {
963
+ !isEmpty(finalChatHistoryList) && <div style={{display: 'flex', justifyContent: 'center'}}>
964
+ <div style={{width: '36px', height: '1px', border: '1px dashed rgb(192, 194, 197)'}}></div>
965
+ <div style={{color:'rgb(192, 194, 197)'}}> 以上是历史消息 </div>
966
+ <div style={{width: '36px', height: '1px', border: '1px dashed rgb(192, 194, 197)'}}></div>
967
+ </div>
968
+ }
969
+ <TabSelector
970
+ welcomeWords={`Hi,欢迎使用${window_title},您可以这样问我:`}
971
+ handleRowClick={(word) => {
972
+ handleSendMessage(word)
973
+ }}
974
+ dataList={questions}
975
+ />
976
+ </div>,
977
+ isSend: false,
978
+ error: false,
979
+ });
980
+ }
953
981
  } catch (error) {
954
982
  console.error("Failed to fetch chat history:", error);
955
983
  }
@@ -958,15 +986,18 @@ export default function ChatWindow({
958
986
  * 当获取历史记录时(sessindId变化时),清空消息,并添加历史记录
959
987
  */
960
988
  useEffect(() => {
961
- sessionIdRef.current = sessionId;
962
- fetchChatHistory().then();
989
+ // 新组件需要等待预置库信息加载完全来载入初始对话引导,旧组件不用
990
+ if (!isEnableForV1 && !isEmpty(questions) || isEnableForV1) {
991
+ sessionIdRef.current = sessionId;
992
+ fetchChatHistory().then();
963
993
 
964
- return () => {
965
- abortControllerRef.current.abort('disconnect');
966
- // abortControllerRef是一次性的,中止之后要初始化,否则fetch请求会被中止导致请求无响应
967
- abortControllerRef.current = new AbortController();
968
- };
969
- }, [sessionId]);
994
+ return () => {
995
+ abortControllerRef.current.abort('disconnect');
996
+ // abortControllerRef是一次性的,中止之后要初始化,否则fetch请求会被中止导致请求无响应
997
+ abortControllerRef.current = new AbortController();
998
+ };
999
+ }
1000
+ }, [sessionId, questions]);
970
1001
 
971
1002
  useEffect(() => {
972
1003
  if (registerChatMethods) {
@@ -1354,7 +1385,6 @@ export default function ChatWindow({
1354
1385
  </>
1355
1386
  )
1356
1387
  }
1357
-
1358
1388
  return (
1359
1389
  <div
1360
1390
  style={{...chat_window_style, width: width, height: "100%"}}
@@ -1378,7 +1408,10 @@ export default function ChatWindow({
1378
1408
  }}
1379
1409
  />
1380
1410
  :
1381
- <div className="cl-middle-container">
1411
+ <div
1412
+ className="cl-middle-container"
1413
+ style={isEnableForV1 ? {paddingLeft: '1.6rem', paddingRight: '1.6rem'} : {}}
1414
+ >
1382
1415
  <div className="cl-header" style={isMobile ? {
1383
1416
  position: 'absolute',
1384
1417
  top: 20,
@@ -1423,6 +1456,7 @@ export default function ChatWindow({
1423
1456
  error={message.error}
1424
1457
  handleSendMessage={handleSendMessage}
1425
1458
  isShowReadIcon={isShowReadIcon}
1459
+ renderInitNode={message.renderInitNode}
1426
1460
  />
1427
1461
  ))
1428
1462
  }
@@ -52,6 +52,8 @@ export default function ChatWidget({
52
52
  isShowReadIcon,
53
53
  renderCustomDropDown,
54
54
  isTagsHidden,
55
+ isEnableForV1 = true,
56
+ questions
55
57
  }: {
56
58
  is_enable_call:boolean,
57
59
  tags: [];
@@ -97,6 +99,8 @@ export default function ChatWidget({
97
99
  isShowReadIcon: boolean,
98
100
  renderCustomDropDown: Function,
99
101
  isTagsHidden: boolean;
102
+ isEnableForV1: boolean;
103
+ questions: any[];
100
104
  }) {
101
105
  const [open, setOpen] = useState(start_open);
102
106
  const [messages, setMessages] = useState<ChatMessageType[]>([]);
@@ -172,6 +176,8 @@ export default function ChatWidget({
172
176
  isShowReadIcon={isShowReadIcon}
173
177
  renderCustomDropDown={renderCustomDropDown}
174
178
  isTagsHidden={isTagsHidden}
179
+ isEnableForV1={isEnableForV1}
180
+ questions={questions}
175
181
  />
176
182
  </div>
177
183
  );
@@ -657,7 +657,7 @@ margin-bottom:1rem;
657
657
  --tw-bg-opacity: 1;
658
658
  padding-left: 1rem;
659
659
  padding-right: 1rem;
660
- padding-top: 0.5rem;
660
+ // padding-top: 0.5rem;
661
661
  padding-bottom: 0.5rem;
662
662
  -ms-overflow-style: none;
663
663
  scrollbar-width: none;
@@ -710,6 +710,11 @@ margin-bottom:1rem;
710
710
  animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
711
711
  }
712
712
 
713
+ .cl-justify-init {
714
+ justify-content: flex-start;
715
+ padding-top:0;
716
+ }
717
+
713
718
  .cl-justify-start {
714
719
  justify-content: flex-start;
715
720
  }
@@ -1,4 +1,4 @@
1
- import React, { useState } from 'react';
1
+ import React, { useEffect, useState } from 'react';
2
2
  import { Tabs, Button, Typography, ConfigProvider } from 'antd';
3
3
  import { LeftOutlined, RightOutlined, SyncOutlined } from '@ant-design/icons';
4
4
  import styles from './index.module.css';
@@ -6,18 +6,8 @@ import styles from './index.module.css';
6
6
  const middleImgUrl = 'https://trans-from-yuntu-resourse.oss-cn-beijing.aliyuncs.com/smartSchool/appCreator/school/bcyz/user/ai/guessYourWant.png';
7
7
  const bottomImgUrl = 'https://trans-from-yuntu-resourse.oss-cn-beijing.aliyuncs.com/kai_yuan/byz/xinge.png';
8
8
 
9
- const defaultMap = {
10
- '学校文化': ['学校最有特色的传统是什么?', '有哪些值得传承的校训?', '学校重视学生个性发展吗?', '有什么知名校友吗?', '新生入学是否有迎新活动?', '学校支持学生创业吗?', '学校节日有哪些特色?', '学校的学习氛围怎么样?', '学生组织有哪些?', '是否有艺术或文化类社团?'],
11
- '校园风景': ['校园内有哪些打卡景点?', '校园绿化做得好吗?', '有湖泊或花园吗?', '有特色建筑吗?', '校园大不大?适合散步吗?', '有哪些适合拍照的地方?', '有室外自习空间吗?', '校园晚上灯光如何?', '有没有露天表演广场?', '有樱花或银杏树吗?'],
12
- '招生流程': ['什么时候开始填志愿?', '招生简章在哪查看?', '是否有预估分数线?', '如何获取往年录取线?', '能否跨省报考?', '有哪些专项招生计划?', '报志愿前可参观校园吗?', '有无强基计划?', '是否有面试环节?', '报名后多久公布录取?'],
13
- '住宿生活': ['几人一间宿舍?', '宿舍有空调吗?', '洗衣机是否自助?', '有独立卫生间吗?', '能否申请调换宿舍?', '有晚归门禁吗?', '网络信号好吗?', '有宿舍文化活动吗?', '宿舍能使用电器吗?', '有快递柜或驿站吗?'],
14
- '餐饮服务': ['食堂饭菜贵不贵?', '食堂口味多样吗?', '有无清真窗口?', '学校周边吃饭方便吗?', '是否支持刷脸就餐?', '饭卡能否线上充值?', '有没有饮品店?', '食堂有无特色菜?', '吃饭时间是否固定?', '是否有外卖平台?'],
15
- '教学资源': ['师资力量如何?', '有外教课程吗?', '是否提供选修课?', '教材是否统一购买?', '有开放实验室吗?', '是否配有学习中心?', '有哪些在线课程平台?', '图书馆开放时间?', '能否跨专业听课?', '有无名师公开课?'],
16
- '就业实习': ['是否提供实习机会?', '就业指导服务如何?', '有哪些合作企业?', '实习是否计入学分?', '就业率有多高?', '毕业生去向有哪些?', '能否推荐实习单位?', '是否有职业规划课?', '能考研继续深造吗?', '就业双选会多不多?'],
17
- };
18
-
19
9
  const TabSelector = ({ customUrl, handleRowClick, welcomeWords, isSimple, dataList = [] }) => {
20
- const [activeKey, setActiveKey] = useState(dataList[0]?.category);
10
+ const [activeKey, setActiveKey] = useState();
21
11
  const [valuePage, setValuePage] = useState(0);
22
12
  const [tabLocation, setTabLocation] = useState(0);
23
13
  const valuesPerPage = 5; // Number of values to show per page
@@ -27,6 +17,11 @@ const TabSelector = ({ customUrl, handleRowClick, welcomeWords, isSimple, dataLi
27
17
  const keys = dataList.map(e=>e.category)||[];
28
18
  const values = dataList.filter(e => activeKey === e.category).map(e => e.data)[0] || [];
29
19
  const visibleValues = isSimple ? values : values.slice(valuePage * valuesPerPage, (valuePage + 1) * valuesPerPage);
20
+
21
+ useEffect(() => {
22
+ setActiveKey(dataList[0]?.category)
23
+ }, [dataList]);
24
+
30
25
  const handleTabChange = (key) => {
31
26
  setActiveKey(key);
32
27
  setValuePage(0); // Reset value page when changing tabs
@@ -138,7 +133,7 @@ const TabSelector = ({ customUrl, handleRowClick, welcomeWords, isSimple, dataLi
138
133
  return (<div className={styles.row} key={index} onClick={() => handleRowClick(item.q)}>
139
134
  <Typography.Paragraph
140
135
  className={styles.text}
141
- style={{ maxWidth: isSimple ? '210px' : '300px' }}
136
+ style={{ maxWidth: isSimple ? '190px' : '300px' }}
142
137
  ellipsis={{ rows: 1, tooltip: `${item.q}`, }}>
143
138
  {isSimple && <span style={{ marginRight: '12px' }}>·</span>}
144
139
  {item.q}
@@ -1,6 +1,6 @@
1
1
  .mainContainer {
2
2
  flex: 1;
3
- height: calc(100% - 220px);
3
+ overflow-y: auto;
4
4
  .welcome {
5
5
  background: #FFFFFF;
6
6
  border-radius: 8px 8px 8px 0px;
@@ -97,7 +97,7 @@
97
97
 
98
98
  .valueList {
99
99
  padding: 10px;
100
- min-height: 200px;
100
+ min-height: 225px;
101
101
  font-size: 16px;
102
102
  color: #000000;
103
103
  overflow-y: auto;
@@ -23,7 +23,7 @@ const CommentIcon = (props) => (
23
23
  <Icon component={commentSvg} {...props} />
24
24
  );
25
25
 
26
- const knowledgeInfo = {
26
+ export const knowledgeInfo = {
27
27
  media: [
28
28
  {
29
29
  a: "https://trans-from-yuntu-resourse.oss-cn-beijing.aliyuncs.com/smartSchool/appCreator/school/bcyz/user/ai/banner.png",
@@ -328,7 +328,7 @@ export class ToolDialogV2 extends React.Component {
328
328
  sessionId: uuidv4(), // 当前激活的对话对应的sessionId
329
329
  dropDownList: [],
330
330
  currentFlow: {},
331
- knowledgeInfo: {...knowledgeInfo},
331
+ knowledgeInfo: {},
332
332
  };
333
333
 
334
334
  componentWillMount() {
@@ -383,6 +383,8 @@ export class ToolDialogV2 extends React.Component {
383
383
  this.setState({ knowledgeInfo: res.data })
384
384
  } else if ( !isEmpty(this.props.knowledgeInfo)) {
385
385
  this.setState({ knowledgeInfo: this.props.knowledgeInfo })
386
+ } else {
387
+ this.setState({ knowledgeInfo: knowledgeInfo })
386
388
  }
387
389
  }
388
390
  }).catch(e => {
@@ -435,6 +437,7 @@ export class ToolDialogV2 extends React.Component {
435
437
  }
436
438
 
437
439
  renderCustomDropDown=(dropDownList)=>{
440
+ return null;
438
441
  const { title } = this.props;
439
442
  const { currentFlow } = this.state;
440
443
  return <TabSelector
@@ -571,6 +574,8 @@ export class ToolDialogV2 extends React.Component {
571
574
  renderCustomDropDown={this.renderCustomDropDown}
572
575
  isTagsHidden={true}
573
576
  placeholder={'请输入您想咨询的问题'}
577
+ isEnableForV1={false}
578
+ questions={this.state.knowledgeInfo?.question || []}
574
579
  />
575
580
  </MethodContext.Provider>
576
581
  </div>