yt-chat-components 1.1.7 → 1.1.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.
@@ -234,7 +234,10 @@ export default function ChatMessage({
234
234
  if (className && className.includes('language-echart')) {
235
235
  try {
236
236
  // 解析代码块内容为 JSON 配置
237
+ // console.log(" --- 1", children.toString().trim())
237
238
  const chartOptions = JSON.parse(children.toString().trim());
239
+ // console.log(" --- 2", chartOptions)
240
+
238
241
  // 渲染 ECharts 组件
239
242
  return <EChartsReact option={chartOptions} style={{minWidth: 500, width: '100%', height: 300, backgroundColor: '#fff' }} />;
240
243
  } catch (error) {
@@ -22,6 +22,8 @@ import typeMobiPng from '../../../assets/aicenter/type-mobi.png';
22
22
  import typeRPubPng from '../../../assets/aicenter/type-rpub.png';
23
23
  import soundWavePng from '../../../assets/aicenter/sound-wave.gif';
24
24
  import luyinPng from '../../../assets/aicenter/luyin.png';
25
+ import phonePng from '../../../assets/aicenter/phone.png';
26
+ import CallInterface from './callInterface/index.tsx';
25
27
  import { RightOutlined } from '@ant-design/icons';
26
28
  import { Image, message as messageTip, Tooltip, Typography } from 'antd';
27
29
  import { isEmpty, isFunction } from 'lodash';
@@ -37,6 +39,7 @@ const setValue = (value) => {
37
39
  };
38
40
 
39
41
  export default function ChatWindow({
42
+ is_enable_call,
40
43
  tags,
41
44
  getHistoryList,
42
45
  userInfo,
@@ -82,6 +85,7 @@ export default function ChatWindow({
82
85
  isMobile = false,
83
86
  isShowChatHeader = true,
84
87
  }: {
88
+ is_enable_call:boolean;
85
89
  tags: [];
86
90
  getHistoryList: Function;
87
91
  userInfo: object;
@@ -127,6 +131,7 @@ export default function ChatWindow({
127
131
  }) {
128
132
  const ref = useRef<HTMLDivElement>(null);
129
133
  const lastMessage = useRef<HTMLDivElement>(null);
134
+ const [showCallInterface, setShowCallInterface] = useState(false); // 添加通话界面状态
130
135
  const [aiStatus, setAiStatus] = useState(null);
131
136
  const inputRef = useRef<HTMLInputElement>(null); /* User input Ref */
132
137
  /* Initial listener for loss of focus that refocuses User input after a small delay */
@@ -449,6 +454,16 @@ export default function ChatWindow({
449
454
  }
450
455
  }
451
456
 
457
+ // 处理打电话按钮点击
458
+ const handleCallButtonClick = () => {
459
+ setShowCallInterface(true);
460
+ };
461
+
462
+ // 处理挂断电话
463
+ const handleHangup = () => {
464
+ setShowCallInterface(false);
465
+ };
466
+
452
467
  /**
453
468
  * 获取文件类型
454
469
  * @param file File 对象
@@ -613,37 +628,70 @@ export default function ChatWindow({
613
628
  /**
614
629
  * 语音实时识别
615
630
  */
616
- const startRecord = ()=>{
617
- if (!('webkitSpeechRecognition' in window)) {
618
- alert('您的浏览器不支持语音识别功能')
631
+ const startRecord = () => {
632
+ // 检查是否支持语音识别API(更通用的检测方式)
633
+ if (!('SpeechRecognition' in window || 'webkitSpeechRecognition' in window)) {
634
+ messageTip.error('您的浏览器不支持语音识别功能,请使用Chrome或Edge浏览器');
619
635
  return;
620
636
  }
621
- if(recordState){
637
+
638
+ // 检查是否在HTTPS环境
639
+ if (window.location.protocol !== 'https:' && window.location.hostname !== 'localhost') {
640
+ messageTip.error('语音识别功能需要在HTTPS环境下使用');
641
+ return;
642
+ }
643
+
644
+ if (recordState) {
622
645
  recognition.stop();
623
646
  setRecordState(false);
624
- }else{
625
- recognition = new webkitSpeechRecognition();
647
+ } else {
648
+ // 使用标准API或webkit前缀版本
649
+ const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
650
+ recognition = new SpeechRecognition();
626
651
  recognition.continuous = true;
627
652
  recognition.interimResults = true;
628
653
  recognition.lang = 'zh-CN';
629
-
654
+
630
655
  recognition.onresult = (event) => {
631
656
  const transcript = Array.from(event.results)
632
657
  .map(result => result[0].transcript)
633
658
  .join('');
634
- setValue(transcript)
659
+ setValue(transcript);
660
+
661
+ // 如果使用的是textarea,还需要更新DOM元素的值
662
+ if (inputRef.current) {
663
+ inputRef.current.value = transcript;
664
+ }
635
665
  };
636
-
666
+
637
667
  recognition.onerror = (event) => {
638
- if(event.error === 'not-allowed'){
639
- messageTip.error("录音权限被拒绝,请允许录音权限后重试")
668
+ if (event.error === 'not-allowed') {
669
+ messageTip.error("录音权限被拒绝,请允许录音权限后重试");
670
+ } else if (event.error === 'no-speech') {
671
+ messageTip.info("未检测到语音,请说话或检查麦克风");
672
+ } else {
673
+ messageTip.error(`语音识别错误: ${event.error}`);
640
674
  }
641
675
  console.error('语音识别错误:', event);
676
+ setRecordState(false);
677
+ };
678
+
679
+ recognition.onend = () => {
680
+ // 如果不是手动停止的,则可能是出错或自动结束
681
+ if (recordState) {
682
+ setRecordState(false);
683
+ }
642
684
  };
643
- recognition.start()
644
- setRecordState(true);
685
+
686
+ try {
687
+ recognition.start();
688
+ setRecordState(true);
689
+ } catch (error) {
690
+ messageTip.error("启动语音识别失败,请检查浏览器设置");
691
+ console.error("启动语音识别失败:", error);
692
+ }
645
693
  }
646
- }
694
+ };
647
695
 
648
696
  /**
649
697
  * 输出消息时,滚动到底部
@@ -754,7 +802,7 @@ export default function ChatWindow({
754
802
  if (isEmpty(dropManUrl)){
755
803
  return (
756
804
  <div className='cl-drop-down'>
757
- <div className="drop-down-title">Hi,ssss欢迎使用{window_title},您可以这样问我:</div>
805
+ <div className="drop-down-title">Hi,欢迎使用{window_title},您可以这样问我:</div>
758
806
  <div className="drop-down-list">
759
807
  {dropDownList.map(({backgroundImg, title}) => (
760
808
  <div className="drop-down-item-card" key={title}>
@@ -995,7 +1043,18 @@ export default function ChatWindow({
995
1043
  </div>
996
1044
  </Tooltip>
997
1045
  }
998
- {/*<Tooltip title="支持PDF / Word / Excel / Markdown / txt / mobi / rpub">*/}
1046
+ {
1047
+ is_enable_call &&
1048
+ <Tooltip title="语音通话">
1049
+ <div
1050
+ className="w_send_voice_box"
1051
+ style={sendingMessage ? { cursor: 'not-allowed' } : {}}
1052
+ onClick={handleCallButtonClick}
1053
+ >
1054
+ <img src={phonePng} style={{ width: 23 }}></img>
1055
+ </div>
1056
+ </Tooltip>
1057
+ }
999
1058
  {
1000
1059
  isShowUploadButton &&
1001
1060
  <Tooltip title="支持图片格式">
@@ -1038,11 +1097,25 @@ export default function ChatWindow({
1038
1097
  )
1039
1098
  }
1040
1099
  return (
1041
- <div
1042
- style={{...chat_window_style, width: width, height: "100%"}}
1043
- ref={ref}
1044
- className="cl-window"
1045
- >
1100
+ <div
1101
+ style={{...chat_window_style, width: width, height: "100%"}}
1102
+ ref={ref}
1103
+ className="cl-window"
1104
+ >
1105
+
1106
+ {/* 添加通话界面 */}
1107
+ {is_enable_call && showCallInterface ?
1108
+ <CallInterface
1109
+ onHangup={handleHangup}
1110
+ contactName={window_title}
1111
+ contactAvatar={agentUrl}
1112
+ api_key={api_key}
1113
+ flowId={flowId}
1114
+ sessionId={sessionId}
1115
+ hostUrl={hostUrl}
1116
+ onMessage={addMessage}
1117
+ />
1118
+ :
1046
1119
  <div className="cl-middle-container">
1047
1120
  <div className="cl-header" style={isMobile ? {position: 'absolute', top: 20, left: 0, paddingLeft: '1.6rem', paddingRight: '1.6rem'} : {}}>
1048
1121
  {
@@ -1051,7 +1124,7 @@ export default function ChatWindow({
1051
1124
  {
1052
1125
  isTitleSideIcon ?
1053
1126
  <img className="p_logoImg" style={{width: logoWidth, height: 'auto', marginRight: 10}}
1054
- src={agentUrl}/> :
1127
+ src={agentUrl}/> :
1055
1128
  <span className="diamond"/>
1056
1129
  }
1057
1130
  {window_title}
@@ -1102,7 +1175,8 @@ export default function ChatWindow({
1102
1175
  {
1103
1176
  renderInputArea()
1104
1177
  }
1105
- </div>
1178
+ </div>
1179
+ }
1106
1180
  </div>
1107
1181
  );
1108
1182
  }
@@ -4,6 +4,7 @@ import ChatWindow from './chatWindow';
4
4
  import { ChatMessageType } from './chatWindow/types/chatWidget';
5
5
 
6
6
  export default function ChatWidget({
7
+ is_enable_call,
7
8
  tags,
8
9
  getHistoryList,
9
10
  userInfo,
@@ -44,6 +45,7 @@ export default function ChatWidget({
44
45
  isMobile = false,
45
46
  isShowChatHeader = true,
46
47
  }: {
48
+ is_enable_call:boolean,
47
49
  tags: [];
48
50
  getHistoryList: Function;
49
51
  userInfo: object;
@@ -2543,6 +2545,7 @@ input::-ms-input-placeholder { /* Microsoft Edge */
2543
2545
  <div style={{ position: 'relative',height:'100%' }}>
2544
2546
  <style dangerouslySetInnerHTML={{ __html: styles + markdownBody + yt_style }}></style>
2545
2547
  <ChatWindow
2548
+ is_enable_call={is_enable_call}
2546
2549
  tags={tags}
2547
2550
  getHistoryList={getHistoryList}
2548
2551
  userInfo={userInfo}
@@ -502,6 +502,7 @@ export class ToolDialog extends React.Component {
502
502
  window_title={currentFlow?.name || title}
503
503
  flow_id={currentFlow?.id || flowId}
504
504
  tags={currentFlow?.keywords || tags}
505
+ is_enable_call={currentFlow?.is_enable_call || false}
505
506
  host_url={hostUrl}
506
507
  api_key={api_key}
507
508
  session_id={this.state.sessionId}
Binary file