yt-chat-components 1.1.7 → 1.1.9
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/build/asset-manifest.json +19 -0
- package/build/index.html +1 -0
- package/build/static/css/main.8ee59d98.css +2 -0
- package/build/static/css/main.8ee59d98.css.map +1 -0
- package/build/static/js/main.ae39ed55.js +3 -0
- package/build/static/js/main.ae39ed55.js.LICENSE.txt +181 -0
- package/build/static/js/main.ae39ed55.js.map +1 -0
- package/build/static/media/aiavatar.74bafa995cce4c01b804.png +0 -0
- package/build/static/media/history-list-empty.1eb65b1550aef4e8c8a4.png +0 -0
- package/build/static/media/icon_history_headerbg.50747e81d01257f55346.png +0 -0
- package/build/static/media/moreAi.285e66289f838072060c.png +0 -0
- package/build/static/media/moreBg.9fc998472925cecd89f2.png +0 -0
- package/build/static/media/phone.19bc6f0d2e9eae4863ae.png +0 -0
- package/package.json +3 -3
- package/public/index.html +2 -2
- package/src/YtChatView/chatWidget/chatWindow/callInterface/index.module.css +51 -0
- package/src/YtChatView/chatWidget/chatWindow/callInterface/index.tsx +553 -0
- package/src/YtChatView/chatWidget/chatWindow/callInterface/style.ts +45 -0
- package/src/YtChatView/chatWidget/chatWindow/chatMessage/index.tsx +3 -0
- package/src/YtChatView/chatWidget/chatWindow/index.tsx +101 -24
- package/src/YtChatView/chatWidget/index.tsx +3 -0
- package/src/YtChatView/previewDialog/index.jsx +2 -1
- package/src/assets/aicenter/ai_call_thinking.png +0 -0
- package/src/assets/aicenter/ai_call_working.gif +0 -0
- package/src/assets/aicenter/phone.png +0 -0
- package/dist/build/static/js/bundle.min.js +0 -1
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export const callStyle = `
|
|
2
|
+
.call-interface {
|
|
3
|
+
width: 100%;
|
|
4
|
+
height: 100%;
|
|
5
|
+
display: flex;
|
|
6
|
+
flex-direction: column;
|
|
7
|
+
justify-content: space-between;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.call-header {
|
|
11
|
+
padding-top: 100px;
|
|
12
|
+
display: flex;
|
|
13
|
+
flex-direction: column;
|
|
14
|
+
align-items: center;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.contact-info {
|
|
18
|
+
display: flex;
|
|
19
|
+
flex-direction: column;
|
|
20
|
+
align-items: center;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.contact-info h2 {
|
|
24
|
+
margin-top: 20px;
|
|
25
|
+
margin-bottom: 5px;
|
|
26
|
+
font-size: 24px;
|
|
27
|
+
color: #333;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.call-status {
|
|
31
|
+
color: #666;
|
|
32
|
+
font-size: 16px;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.call-controls {
|
|
36
|
+
padding-bottom: 100px;
|
|
37
|
+
display: flex;
|
|
38
|
+
justify-content: center;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.hangup-icon {
|
|
42
|
+
font-size: 24px;
|
|
43
|
+
color: white;
|
|
44
|
+
}
|
|
45
|
+
`
|
|
@@ -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 */
|
|
@@ -447,8 +452,19 @@ export default function ChatWindow({
|
|
|
447
452
|
});
|
|
448
453
|
setDropDownList(undefined);
|
|
449
454
|
}
|
|
455
|
+
inputRef.current.value=''
|
|
450
456
|
}
|
|
451
457
|
|
|
458
|
+
// 处理打电话按钮点击
|
|
459
|
+
const handleCallButtonClick = () => {
|
|
460
|
+
setShowCallInterface(true);
|
|
461
|
+
};
|
|
462
|
+
|
|
463
|
+
// 处理挂断电话
|
|
464
|
+
const handleHangup = () => {
|
|
465
|
+
setShowCallInterface(false);
|
|
466
|
+
};
|
|
467
|
+
|
|
452
468
|
/**
|
|
453
469
|
* 获取文件类型
|
|
454
470
|
* @param file File 对象
|
|
@@ -613,37 +629,70 @@ export default function ChatWindow({
|
|
|
613
629
|
/**
|
|
614
630
|
* 语音实时识别
|
|
615
631
|
*/
|
|
616
|
-
const startRecord = ()=>{
|
|
617
|
-
|
|
618
|
-
|
|
632
|
+
const startRecord = () => {
|
|
633
|
+
// 检查是否支持语音识别API(更通用的检测方式)
|
|
634
|
+
if (!('SpeechRecognition' in window || 'webkitSpeechRecognition' in window)) {
|
|
635
|
+
messageTip.error('您的浏览器不支持语音识别功能,请使用Chrome或Edge浏览器');
|
|
619
636
|
return;
|
|
620
637
|
}
|
|
621
|
-
|
|
638
|
+
|
|
639
|
+
// 检查是否在HTTPS环境
|
|
640
|
+
if (window.location.protocol !== 'https:' && window.location.hostname !== 'localhost') {
|
|
641
|
+
messageTip.error('语音识别功能需要在HTTPS环境下使用');
|
|
642
|
+
return;
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
if (recordState) {
|
|
622
646
|
recognition.stop();
|
|
623
647
|
setRecordState(false);
|
|
624
|
-
}else{
|
|
625
|
-
|
|
648
|
+
} else {
|
|
649
|
+
// 使用标准API或webkit前缀版本
|
|
650
|
+
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
|
|
651
|
+
recognition = new SpeechRecognition();
|
|
626
652
|
recognition.continuous = true;
|
|
627
653
|
recognition.interimResults = true;
|
|
628
654
|
recognition.lang = 'zh-CN';
|
|
629
|
-
|
|
655
|
+
|
|
630
656
|
recognition.onresult = (event) => {
|
|
631
657
|
const transcript = Array.from(event.results)
|
|
632
658
|
.map(result => result[0].transcript)
|
|
633
659
|
.join('');
|
|
634
|
-
setValue(transcript)
|
|
660
|
+
setValue(transcript);
|
|
661
|
+
|
|
662
|
+
// 如果使用的是textarea,还需要更新DOM元素的值
|
|
663
|
+
if (inputRef.current) {
|
|
664
|
+
inputRef.current.value = transcript;
|
|
665
|
+
}
|
|
635
666
|
};
|
|
636
|
-
|
|
667
|
+
|
|
637
668
|
recognition.onerror = (event) => {
|
|
638
|
-
if(event.error === 'not-allowed'){
|
|
639
|
-
messageTip.error("录音权限被拒绝,请允许录音权限后重试")
|
|
669
|
+
if (event.error === 'not-allowed') {
|
|
670
|
+
messageTip.error("录音权限被拒绝,请允许录音权限后重试");
|
|
671
|
+
} else if (event.error === 'no-speech') {
|
|
672
|
+
messageTip.info("未检测到语音,请说话或检查麦克风");
|
|
673
|
+
} else {
|
|
674
|
+
messageTip.error(`语音识别错误: ${event.error}`);
|
|
640
675
|
}
|
|
641
676
|
console.error('语音识别错误:', event);
|
|
677
|
+
setRecordState(false);
|
|
678
|
+
};
|
|
679
|
+
|
|
680
|
+
recognition.onend = () => {
|
|
681
|
+
// 如果不是手动停止的,则可能是出错或自动结束
|
|
682
|
+
if (recordState) {
|
|
683
|
+
setRecordState(false);
|
|
684
|
+
}
|
|
642
685
|
};
|
|
643
|
-
|
|
644
|
-
|
|
686
|
+
|
|
687
|
+
try {
|
|
688
|
+
recognition.start();
|
|
689
|
+
setRecordState(true);
|
|
690
|
+
} catch (error) {
|
|
691
|
+
messageTip.error("启动语音识别失败,请检查浏览器设置");
|
|
692
|
+
console.error("启动语音识别失败:", error);
|
|
693
|
+
}
|
|
645
694
|
}
|
|
646
|
-
}
|
|
695
|
+
};
|
|
647
696
|
|
|
648
697
|
/**
|
|
649
698
|
* 输出消息时,滚动到底部
|
|
@@ -754,7 +803,7 @@ export default function ChatWindow({
|
|
|
754
803
|
if (isEmpty(dropManUrl)){
|
|
755
804
|
return (
|
|
756
805
|
<div className='cl-drop-down'>
|
|
757
|
-
<div className="drop-down-title">Hi
|
|
806
|
+
<div className="drop-down-title">Hi,欢迎使用{window_title},您可以这样问我:</div>
|
|
758
807
|
<div className="drop-down-list">
|
|
759
808
|
{dropDownList.map(({backgroundImg, title}) => (
|
|
760
809
|
<div className="drop-down-item-card" key={title}>
|
|
@@ -963,7 +1012,7 @@ export default function ChatWindow({
|
|
|
963
1012
|
<div className="w_inputBox" style={{height: inputContainerHeight}}>
|
|
964
1013
|
<textarea
|
|
965
1014
|
onFocus={()=>setInputContainerHeight('120px')}
|
|
966
|
-
onBlur={()=>setInputContainerHeight('50px')}
|
|
1015
|
+
onBlur={() => setTimeout(() => setInputContainerHeight('50px'), 200)}
|
|
967
1016
|
// value={inputValue}
|
|
968
1017
|
onChange={(e) => setValue(e.target.value)}
|
|
969
1018
|
onKeyDown={(e) => {
|
|
@@ -995,7 +1044,18 @@ export default function ChatWindow({
|
|
|
995
1044
|
</div>
|
|
996
1045
|
</Tooltip>
|
|
997
1046
|
}
|
|
998
|
-
{
|
|
1047
|
+
{
|
|
1048
|
+
is_enable_call &&
|
|
1049
|
+
<Tooltip title="语音通话">
|
|
1050
|
+
<div
|
|
1051
|
+
className="w_send_voice_box"
|
|
1052
|
+
style={sendingMessage ? { cursor: 'not-allowed' } : {}}
|
|
1053
|
+
onClick={handleCallButtonClick}
|
|
1054
|
+
>
|
|
1055
|
+
<img src={phonePng} style={{ width: 23 }}></img>
|
|
1056
|
+
</div>
|
|
1057
|
+
</Tooltip>
|
|
1058
|
+
}
|
|
999
1059
|
{
|
|
1000
1060
|
isShowUploadButton &&
|
|
1001
1061
|
<Tooltip title="支持图片格式">
|
|
@@ -1013,6 +1073,7 @@ export default function ChatWindow({
|
|
|
1013
1073
|
style={{ ...(sendingMessage ? { cursor: 'pointer' } : {}), padding: '0 13px', background:'transparent', display:'flex', alignItems:'center', justifyContent:'center' }}
|
|
1014
1074
|
onClick={() => {
|
|
1015
1075
|
if(sendingMessage){
|
|
1076
|
+
// 如果正在发送消息,此时点击则为取消发送
|
|
1016
1077
|
const output = {
|
|
1017
1078
|
message:nowAIContent,
|
|
1018
1079
|
type:'text'
|
|
@@ -1038,11 +1099,26 @@ export default function ChatWindow({
|
|
|
1038
1099
|
)
|
|
1039
1100
|
}
|
|
1040
1101
|
return (
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1102
|
+
<div
|
|
1103
|
+
style={{...chat_window_style, width: width, height: "100%"}}
|
|
1104
|
+
ref={ref}
|
|
1105
|
+
className="cl-window"
|
|
1106
|
+
>
|
|
1107
|
+
|
|
1108
|
+
{/* 添加通话界面 */}
|
|
1109
|
+
{is_enable_call && showCallInterface ?
|
|
1110
|
+
<CallInterface
|
|
1111
|
+
onHangup={handleHangup}
|
|
1112
|
+
contactName={window_title}
|
|
1113
|
+
contactAvatar={agentUrl}
|
|
1114
|
+
api_key={api_key}
|
|
1115
|
+
flowId={flowId}
|
|
1116
|
+
sessionId={sessionId}
|
|
1117
|
+
hostUrl={hostUrl}
|
|
1118
|
+
onMessage={addMessage}
|
|
1119
|
+
userInfo={userInfo}
|
|
1120
|
+
/>
|
|
1121
|
+
:
|
|
1046
1122
|
<div className="cl-middle-container">
|
|
1047
1123
|
<div className="cl-header" style={isMobile ? {position: 'absolute', top: 20, left: 0, paddingLeft: '1.6rem', paddingRight: '1.6rem'} : {}}>
|
|
1048
1124
|
{
|
|
@@ -1051,7 +1127,7 @@ export default function ChatWindow({
|
|
|
1051
1127
|
{
|
|
1052
1128
|
isTitleSideIcon ?
|
|
1053
1129
|
<img className="p_logoImg" style={{width: logoWidth, height: 'auto', marginRight: 10}}
|
|
1054
|
-
|
|
1130
|
+
src={agentUrl}/> :
|
|
1055
1131
|
<span className="diamond"/>
|
|
1056
1132
|
}
|
|
1057
1133
|
{window_title}
|
|
@@ -1102,7 +1178,8 @@ export default function ChatWindow({
|
|
|
1102
1178
|
{
|
|
1103
1179
|
renderInputArea()
|
|
1104
1180
|
}
|
|
1105
|
-
|
|
1181
|
+
</div>
|
|
1182
|
+
}
|
|
1106
1183
|
</div>
|
|
1107
1184
|
);
|
|
1108
1185
|
}
|
|
@@ -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}
|
|
@@ -350,7 +350,7 @@ export class ToolDialog extends React.Component {
|
|
|
350
350
|
|
|
351
351
|
// 获取历史对话列表
|
|
352
352
|
getHistoryList = (sceneData, isRefreshWords) => {
|
|
353
|
-
const { sceneId, appId: flowId, isShowSideLeft } = this.props;
|
|
353
|
+
const { sceneId, appId: flowId, isShowSideLeft = true } = this.props;
|
|
354
354
|
if(isEmpty(sceneId)){
|
|
355
355
|
// 单独组件情况
|
|
356
356
|
if(isRefreshWords){
|
|
@@ -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
|
|
Binary file
|
|
Binary file
|