yt-chat-components 1.3.7 → 1.3.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/package.json +1 -2
- package/public/index.html +4 -6
- package/src/YtChatView/chatWidget/chatWindow/chatMessage/CustomThoughtChain.module.css +123 -0
- package/src/YtChatView/chatWidget/chatWindow/chatMessage/CustomThoughtChain.tsx +214 -0
- package/src/YtChatView/chatWidget/chatWindow/chatMessage/index.tsx +57 -29
- package/src/YtChatView/chatWidget/chatWindow/chatMessage/urlCard.tsx +146 -0
- package/src/YtChatView/chatWidget/chatWindow/index.tsx +1 -1
- package/src/YtChatView/chatWidget/chatWindow/types/chatWidget/index.ts +2 -1
- package/src/YtChatView/chatWidget/index.tsx +3 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "yt-chat-components",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.9",
|
|
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",
|
|
@@ -11,7 +11,6 @@
|
|
|
11
11
|
},
|
|
12
12
|
"dependencies": {
|
|
13
13
|
"@ant-design/icons": "5.0.0",
|
|
14
|
-
"@ant-design/x": "^1.1.1",
|
|
15
14
|
"@testing-library/jest-dom": "^5.16.5",
|
|
16
15
|
"@testing-library/react": "^13.4.0",
|
|
17
16
|
"@testing-library/user-event": "^13.5.0",
|
package/public/index.html
CHANGED
|
@@ -14,9 +14,9 @@
|
|
|
14
14
|
height="50"
|
|
15
15
|
title="菜鸟驿站"
|
|
16
16
|
icon-url="https://trans-from-yuntu-resourse.oss-cn-beijing.aliyuncs.com/smartSchool/appCreator/school/ccit/user/xc//image/ebfaf4da-c1d9-46fb-a0b1-f159e95cffc2_AI招生咨询小助手.png"
|
|
17
|
-
host-url="
|
|
18
|
-
user-info='{"id": "123", "name": "John Doe", "code":"
|
|
19
|
-
app-id="
|
|
17
|
+
host-url="http://localhost:7860"
|
|
18
|
+
user-info='{"id": "123", "name": "John Doe", "code":"2020230608" }'
|
|
19
|
+
app-id="c3148c58-c2a2-45a2-a872-bb6e7fc2dd7e"
|
|
20
20
|
is-show-side-left=true
|
|
21
21
|
is-show-side-right=false
|
|
22
22
|
modal-index="9999999999"
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
logo-font-size="26px"
|
|
29
29
|
logo-position="fixed"
|
|
30
30
|
is-title-side-icon=false
|
|
31
|
+
is-show-upload-button=true
|
|
31
32
|
/>
|
|
32
33
|
</body>
|
|
33
34
|
|
|
@@ -50,7 +51,6 @@
|
|
|
50
51
|
<!-- is-title-side-icon=true-->
|
|
51
52
|
<!-- is-show-upload-button=false-->
|
|
52
53
|
<!-- drop-man-url="https://trans-from-yuntu-resourse.oss-cn-beijing.aliyuncs.com/smartSchool/appCreator/ai/ai_man01.png"-->
|
|
53
|
-
<!--is-show-read-icon=false-->
|
|
54
54
|
<!--/>-->
|
|
55
55
|
<!--</body>-->
|
|
56
56
|
|
|
@@ -77,7 +77,6 @@
|
|
|
77
77
|
<!-- logo-position="fixed"-->
|
|
78
78
|
<!-- is-title-side-icon=false-->
|
|
79
79
|
<!-- is-show-upload-button=false-->
|
|
80
|
-
<!--is-show-read-icon=false-->
|
|
81
80
|
<!--/>-->
|
|
82
81
|
<!--</body>-->
|
|
83
82
|
|
|
@@ -104,7 +103,6 @@
|
|
|
104
103
|
<!-- is-title-side-icon=true-->
|
|
105
104
|
<!-- is-show-upload-button=false-->
|
|
106
105
|
<!-- drop-man-url="https://trans-from-yuntu-resourse.oss-cn-beijing.aliyuncs.com/smartSchool/appCreator/ai/ai_man01.png"-->
|
|
107
|
-
<!--is-show-read-icon=false-->
|
|
108
106
|
<!--/>-->
|
|
109
107
|
<!--</body>-->
|
|
110
108
|
</html>
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
.custom-thought-chain {
|
|
2
|
+
display: flex;
|
|
3
|
+
flex-direction: column;
|
|
4
|
+
width: 100%;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
/* 思维链节点项样式 */
|
|
8
|
+
.custom-thought-chain-item {
|
|
9
|
+
position: relative;
|
|
10
|
+
display: flex;
|
|
11
|
+
flex-direction: column;
|
|
12
|
+
padding-left: 40px;
|
|
13
|
+
margin-bottom: 16px;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.custom-thought-chain-item-last {
|
|
17
|
+
position: relative;
|
|
18
|
+
display: flex;
|
|
19
|
+
flex-direction: column;
|
|
20
|
+
padding-left: 40px;
|
|
21
|
+
margin-bottom: 16px;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.custom-thought-chain-item-last::before {
|
|
25
|
+
content: '';
|
|
26
|
+
position: absolute;
|
|
27
|
+
top: 24px;
|
|
28
|
+
left: 20px;
|
|
29
|
+
width: 2px;
|
|
30
|
+
height: calc(100% - 8px);
|
|
31
|
+
background-color: #4270f5;
|
|
32
|
+
z-index: 1;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/* 节点连接线样式 */
|
|
36
|
+
.custom-thought-chain-item::before {
|
|
37
|
+
content: '';
|
|
38
|
+
position: absolute;
|
|
39
|
+
top: 24px;
|
|
40
|
+
left: 20px;
|
|
41
|
+
width: 2px;
|
|
42
|
+
height: calc(100% - 8px);
|
|
43
|
+
background-color: #52c41a;
|
|
44
|
+
z-index: 1;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/* 节点头部样式 */
|
|
48
|
+
.custom-thought-chain-item-header {
|
|
49
|
+
display: flex;
|
|
50
|
+
align-items: flex-start;
|
|
51
|
+
margin-bottom: 8px;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/* 节点图标样式 */
|
|
55
|
+
.custom-thought-chain-item-icon {
|
|
56
|
+
position: absolute;
|
|
57
|
+
left: 9px;
|
|
58
|
+
top: -1px;
|
|
59
|
+
width: 25px;
|
|
60
|
+
height: 25px;
|
|
61
|
+
display: flex;
|
|
62
|
+
align-items: center;
|
|
63
|
+
justify-content: center;
|
|
64
|
+
background-color: #52c41a;
|
|
65
|
+
border-radius: 50%;
|
|
66
|
+
color: white;
|
|
67
|
+
font-size: 15px;
|
|
68
|
+
z-index: 2;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.custom-thought-chain-item-icon-last {
|
|
72
|
+
position: absolute;
|
|
73
|
+
left: 9px;
|
|
74
|
+
top: -1px;
|
|
75
|
+
width: 25px;
|
|
76
|
+
height: 25px;
|
|
77
|
+
display: flex;
|
|
78
|
+
align-items: center;
|
|
79
|
+
justify-content: center;
|
|
80
|
+
background-color: #4270f5;
|
|
81
|
+
border-radius: 50%;
|
|
82
|
+
color: white;
|
|
83
|
+
font-size: 15px;
|
|
84
|
+
z-index: 2;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/* 标题容器样式 */
|
|
88
|
+
.custom-thought-chain-item-title-container {
|
|
89
|
+
flex: 1;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/* 标题样式 */
|
|
93
|
+
.custom-thought-chain-item-title {
|
|
94
|
+
font-weight: 500;
|
|
95
|
+
color: rgba(0, 0, 0, 0.85);
|
|
96
|
+
margin-bottom: 4px;
|
|
97
|
+
display: flex;
|
|
98
|
+
align-items: center;
|
|
99
|
+
margin-left: 8px;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/* 描述样式 */
|
|
103
|
+
.custom-thought-chain-item-description {
|
|
104
|
+
font-size: 14px;
|
|
105
|
+
color: rgba(0, 0, 0, 0.45);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/* 内容样式 */
|
|
109
|
+
.custom-thought-chain-item-content {
|
|
110
|
+
margin-bottom: 8px;
|
|
111
|
+
background: white;
|
|
112
|
+
padding: 12px;
|
|
113
|
+
border-radius: 8px;
|
|
114
|
+
border: 1px solid #f0f0f0;
|
|
115
|
+
margin-left: -30px;
|
|
116
|
+
z-index: 2;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/* 页脚样式 */
|
|
120
|
+
.custom-thought-chain-item-footer {
|
|
121
|
+
display: flex;
|
|
122
|
+
gap: 8px;
|
|
123
|
+
}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { CheckCircleOutlined, EllipsisOutlined, InfoCircleOutlined } from '@ant-design/icons';
|
|
4
|
+
|
|
5
|
+
export const customThoughtChainStyle = `
|
|
6
|
+
/* 思维链容器样式 */
|
|
7
|
+
.custom-thought-chain {
|
|
8
|
+
display: flex;
|
|
9
|
+
flex-direction: column;
|
|
10
|
+
width: 100%;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/* 思维链节点项样式 */
|
|
14
|
+
.custom-thought-chain-item {
|
|
15
|
+
position: relative;
|
|
16
|
+
display: flex;
|
|
17
|
+
flex-direction: column;
|
|
18
|
+
padding-left: 40px;
|
|
19
|
+
margin-bottom: 16px;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.custom-thought-chain-item-last {
|
|
23
|
+
position: relative;
|
|
24
|
+
display: flex;
|
|
25
|
+
flex-direction: column;
|
|
26
|
+
padding-left: 40px;
|
|
27
|
+
margin-bottom: 16px;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.custom-thought-chain-item-last::before {
|
|
31
|
+
content: '';
|
|
32
|
+
position: absolute;
|
|
33
|
+
top: 24px;
|
|
34
|
+
left: 20px;
|
|
35
|
+
width: 2px;
|
|
36
|
+
height: calc(100% - 8px);
|
|
37
|
+
background-color: #4270f5;
|
|
38
|
+
z-index: 1;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/* 节点连接线样式 */
|
|
42
|
+
.custom-thought-chain-item::before {
|
|
43
|
+
content: '';
|
|
44
|
+
position: absolute;
|
|
45
|
+
top: 24px;
|
|
46
|
+
left: 20px;
|
|
47
|
+
width: 2px;
|
|
48
|
+
height: calc(100% - 8px);
|
|
49
|
+
background-color: #52c41a;
|
|
50
|
+
z-index: 1;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/* 节点头部样式 */
|
|
54
|
+
.custom-thought-chain-item-header {
|
|
55
|
+
display: flex;
|
|
56
|
+
align-items: flex-start;
|
|
57
|
+
margin-bottom: 8px;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/* 节点图标样式 */
|
|
61
|
+
.custom-thought-chain-item-icon {
|
|
62
|
+
position: absolute;
|
|
63
|
+
left: 9px;
|
|
64
|
+
top: -1px;
|
|
65
|
+
width: 25px;
|
|
66
|
+
height: 25px;
|
|
67
|
+
display: flex;
|
|
68
|
+
align-items: center;
|
|
69
|
+
justify-content: center;
|
|
70
|
+
background-color: #52c41a;
|
|
71
|
+
border-radius: 50%;
|
|
72
|
+
color: white;
|
|
73
|
+
font-size: 15px;
|
|
74
|
+
z-index: 2;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.custom-thought-chain-item-icon-last {
|
|
78
|
+
position: absolute;
|
|
79
|
+
left: 9px;
|
|
80
|
+
top: -1px;
|
|
81
|
+
width: 25px;
|
|
82
|
+
height: 25px;
|
|
83
|
+
display: flex;
|
|
84
|
+
align-items: center;
|
|
85
|
+
justify-content: center;
|
|
86
|
+
background-color: #4270f5;
|
|
87
|
+
border-radius: 50%;
|
|
88
|
+
color: white;
|
|
89
|
+
font-size: 15px;
|
|
90
|
+
z-index: 2;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/* 标题容器样式 */
|
|
94
|
+
.custom-thought-chain-item-title-container {
|
|
95
|
+
flex: 1;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/* 标题样式 */
|
|
99
|
+
.custom-thought-chain-item-title {
|
|
100
|
+
font-weight: 500;
|
|
101
|
+
color: rgba(0, 0, 0, 0.85);
|
|
102
|
+
margin-bottom: 4px;
|
|
103
|
+
display: flex;
|
|
104
|
+
align-items: center;
|
|
105
|
+
margin-left: 8px;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/* 描述样式 */
|
|
109
|
+
.custom-thought-chain-item-description {
|
|
110
|
+
font-size: 14px;
|
|
111
|
+
color: rgba(0, 0, 0, 0.45);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/* 内容样式 */
|
|
115
|
+
.custom-thought-chain-item-content {
|
|
116
|
+
margin-bottom: 8px;
|
|
117
|
+
background: white;
|
|
118
|
+
padding: 12px;
|
|
119
|
+
border-radius: 8px;
|
|
120
|
+
border: 1px solid #f0f0f0;
|
|
121
|
+
margin-left: -30px;
|
|
122
|
+
z-index: 2;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/* 页脚样式 */
|
|
126
|
+
.custom-thought-chain-item-footer {
|
|
127
|
+
display: flex;
|
|
128
|
+
gap: 8px;
|
|
129
|
+
}
|
|
130
|
+
`
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* 自定义思维链节点项接口
|
|
134
|
+
*/
|
|
135
|
+
export interface CustomThoughtChainItem {
|
|
136
|
+
title: React.ReactNode;
|
|
137
|
+
description?: React.ReactNode;
|
|
138
|
+
content?: React.ReactNode;
|
|
139
|
+
footer?: React.ReactNode;
|
|
140
|
+
icon?: React.ReactNode;
|
|
141
|
+
status?: 'pending' | 'success' | 'error';
|
|
142
|
+
key?: string;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* 自定义思维链组件接口
|
|
147
|
+
*/
|
|
148
|
+
export interface CustomThoughtChainProps {
|
|
149
|
+
items: CustomThoughtChainItem[];
|
|
150
|
+
size?: 'large' | 'middle' | 'small';
|
|
151
|
+
collapsible?: boolean;
|
|
152
|
+
styles?: Record<string, React.CSSProperties>;
|
|
153
|
+
classNames?: Record<string, string>;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* 思维链节点项组件
|
|
158
|
+
* @param props 节点项属性
|
|
159
|
+
* @returns 思维链节点项组件
|
|
160
|
+
*/
|
|
161
|
+
const ThoughtChainItem: React.FC<CustomThoughtChainItem & {
|
|
162
|
+
size?: 'large' | 'middle' | 'small';
|
|
163
|
+
}> = (props) => {
|
|
164
|
+
const { title, description, content, footer, icon, status = 'success', size = 'middle', isLast } = props;
|
|
165
|
+
return (
|
|
166
|
+
<div className={`${status === 'pending' ? 'custom-thought-chain-item-last' : 'custom-thought-chain-item'}`}>
|
|
167
|
+
<div className="custom-thought-chain-item-header">
|
|
168
|
+
<div className={`${status === 'pending' ? 'custom-thought-chain-item-icon-last' : 'custom-thought-chain-item-icon'}`}>
|
|
169
|
+
{icon}
|
|
170
|
+
</div>
|
|
171
|
+
<div className="custom-thought-chain-item-title-container">
|
|
172
|
+
{title && <div className="custom-thought-chain-item-title">{title}</div>}
|
|
173
|
+
{description && <div className="custom-thought-chain-item-description">{description}</div>}
|
|
174
|
+
</div>
|
|
175
|
+
</div>
|
|
176
|
+
{content && (
|
|
177
|
+
<div className="custom-thought-chain-item-content">
|
|
178
|
+
{content}
|
|
179
|
+
</div>
|
|
180
|
+
)}
|
|
181
|
+
{footer && (
|
|
182
|
+
<div className="custom-thought-chain-item-footer">
|
|
183
|
+
{footer}
|
|
184
|
+
</div>
|
|
185
|
+
)}
|
|
186
|
+
</div>
|
|
187
|
+
);
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* 自定义思维链组件
|
|
192
|
+
* @param props 思维链组件属性
|
|
193
|
+
* @returns 思维链组件
|
|
194
|
+
*/
|
|
195
|
+
const CustomThoughtChain: React.FC<CustomThoughtChainProps> = (props) => {
|
|
196
|
+
const { items, size = 'middle', collapsible = false, styles = {}, classNames = {} } = props;
|
|
197
|
+
|
|
198
|
+
return (
|
|
199
|
+
<div
|
|
200
|
+
className={`custom-thought-chain ${classNames.item || ''}`}
|
|
201
|
+
style={styles.item}
|
|
202
|
+
>
|
|
203
|
+
{items.map((item, index) => (
|
|
204
|
+
<ThoughtChainItem
|
|
205
|
+
key={item.key || index}
|
|
206
|
+
{...item}
|
|
207
|
+
size={size}
|
|
208
|
+
/>
|
|
209
|
+
))}
|
|
210
|
+
</div>
|
|
211
|
+
);
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
export default CustomThoughtChain;
|
|
@@ -6,7 +6,7 @@ import remarkGfm from 'remark-gfm';
|
|
|
6
6
|
import rehypeMathjax from 'rehype-mathjax';
|
|
7
7
|
// import './index.module.css';
|
|
8
8
|
import upFilePng from '../../../../assets/aicenter/upfile.png';
|
|
9
|
-
import {Button, Collapse, DatePicker, Form, Image, Input, message as messageTip, Select, Skeleton, Avatar} from 'antd';
|
|
9
|
+
import {Button, Collapse, DatePicker, Form, Image, Input, message as messageTip, Select, Skeleton, Avatar, Card} from 'antd';
|
|
10
10
|
import React, {useRef, useState} from 'react';
|
|
11
11
|
import typePdfPng from '../../../../assets/aicenter/type-pdf.png';
|
|
12
12
|
import typeWordPng from '../../../../assets/aicenter/type-word.png';
|
|
@@ -18,11 +18,11 @@ import typeRPubPng from '../../../../assets/aicenter/type-rpub.png';
|
|
|
18
18
|
import playPng from '../../../../assets/aicenter/play.png';
|
|
19
19
|
import playRunGif from '../../../../assets/aicenter/play-run.gif';
|
|
20
20
|
import copyPng from '../../../../assets/aicenter/copy.png';
|
|
21
|
-
import type {ThoughtChainItem} from '@ant-design/x';
|
|
22
|
-
import {ThoughtChain} from '@ant-design/x';
|
|
23
21
|
import {CheckCircleOutlined, EllipsisOutlined, InfoCircleOutlined, ClockCircleOutlined} from '@ant-design/icons';
|
|
24
22
|
import ChatMessagePlaceholder, {ChatMessagePlaceholderInThought} from "../chatPlaceholder";
|
|
25
|
-
|
|
23
|
+
import {UrlCard} from "./urlCard"
|
|
24
|
+
import {CustomThoughtChainItem, CustomThoughtChainProps} from "./CustomThoughtChain";
|
|
25
|
+
import CustomThoughtChain from "./CustomThoughtChain";
|
|
26
26
|
let speechSynth = window.speechSynthesis;
|
|
27
27
|
let utterance = null;
|
|
28
28
|
|
|
@@ -230,27 +230,43 @@ export default function ChatMessage({
|
|
|
230
230
|
}
|
|
231
231
|
|
|
232
232
|
const renderLoading = (type:MessageType, height:number) => {
|
|
233
|
-
const skeletonContainerId = `skeleton-container
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
// 其他类型暂不处理
|
|
242
|
-
(type == MessageType.echart || type == MessageType.form) && (
|
|
233
|
+
const skeletonContainerId = `skeleton-container`;
|
|
234
|
+
if(type == MessageType.echart || type == MessageType.form){
|
|
235
|
+
return (
|
|
236
|
+
<div
|
|
237
|
+
id={skeletonContainerId}
|
|
238
|
+
style={{minWidth: 500, width: '100%', height, display: 'flex', justifyContent: 'center', alignItems: 'center'}}
|
|
239
|
+
>
|
|
240
|
+
{
|
|
243
241
|
<Skeleton.Image active={true} style={{width: '100%', height: '100%'}}/>
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
<style jsx>{`
|
|
242
|
+
}
|
|
243
|
+
<style jsx>{`
|
|
247
244
|
#${skeletonContainerId} .ant-skeleton.ant-skeleton-element {
|
|
248
245
|
width: 100% !important;
|
|
249
246
|
height: 100% !important;
|
|
250
247
|
}
|
|
251
248
|
`}</style>
|
|
252
|
-
|
|
253
|
-
|
|
249
|
+
</div>
|
|
250
|
+
)
|
|
251
|
+
}else if(type === MessageType.url){
|
|
252
|
+
return (
|
|
253
|
+
<div
|
|
254
|
+
id={skeletonContainerId}
|
|
255
|
+
style={{minWidth: 80, width: '100%', height, display: 'flex', justifyContent: 'center', alignItems: 'center'}}
|
|
256
|
+
>
|
|
257
|
+
{
|
|
258
|
+
<Skeleton.Button active={true} shape={'default'} block={true} style={{width: '100%', height: '100%'}}/>
|
|
259
|
+
}
|
|
260
|
+
<style jsx>{`
|
|
261
|
+
#${skeletonContainerId} .ant-skeleton.ant-skeleton-element {
|
|
262
|
+
width: 100% !important;
|
|
263
|
+
height: 100% !important;
|
|
264
|
+
}
|
|
265
|
+
`}</style>
|
|
266
|
+
</div>
|
|
267
|
+
)
|
|
268
|
+
}
|
|
269
|
+
|
|
254
270
|
}
|
|
255
271
|
|
|
256
272
|
// 自定义渲染器
|
|
@@ -284,12 +300,27 @@ export default function ChatMessage({
|
|
|
284
300
|
return renderLoading(MessageType.form, 300);
|
|
285
301
|
}
|
|
286
302
|
}
|
|
303
|
+
// 检查是否是代码块,并且语言为 'url'
|
|
304
|
+
else if (className && className.includes('language-url-config')) {
|
|
305
|
+
try {
|
|
306
|
+
// 解析代码块内容为 JSON 配置
|
|
307
|
+
// console.log(" --- 1 url_config", children.toString().trim().replace(/\\n/g, '').replace('\n', ''))
|
|
308
|
+
const url_config = JSON.parse(children.toString().trim().replace(/\\n/g, '').replace('\n', ''));
|
|
309
|
+
// console.log(" --- 2 url_config", url_config)
|
|
310
|
+
const {app_name, form_name, form_url} = url_config;
|
|
311
|
+
|
|
312
|
+
// 渲染组件
|
|
313
|
+
return <UrlCard url={form_url} appName={app_name} menuName={form_name}/>
|
|
314
|
+
} catch (error) {
|
|
315
|
+
return renderLoading(MessageType.url, 50);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
287
318
|
// 默认渲染其他代码块
|
|
288
319
|
return <code className={className} {...props}>{children}</code>;
|
|
289
320
|
},
|
|
290
321
|
}), [isSubmittingForm]); // 依赖 isSubmittingForm 刷新ui
|
|
291
322
|
|
|
292
|
-
const getStatusIcon = (status:
|
|
323
|
+
const getStatusIcon = (status: CustomThoughtChainItem['status'], icon?: React.ReactNode) => {
|
|
293
324
|
switch (status) {
|
|
294
325
|
case 'success':
|
|
295
326
|
default:
|
|
@@ -318,17 +349,14 @@ export default function ChatMessage({
|
|
|
318
349
|
const renderBotTextMessage = () => {
|
|
319
350
|
const items = messageItemList.map((item, index) => {
|
|
320
351
|
const {id, thinkMessage, message, loadingMessage, type, name, toolCallInfo, rawInfo} = item;
|
|
321
|
-
const
|
|
352
|
+
const isLatestItem = index === messageItemList.length - 1;
|
|
322
353
|
let status = 'success'
|
|
323
|
-
// 只有在接收信息的时候有 pending
|
|
324
|
-
if (receivingMessage && isLatest){
|
|
325
|
-
|
|
326
|
-
if(isLatest){
|
|
327
|
-
status = 'pending'
|
|
328
|
-
}
|
|
354
|
+
// 只有在接收信息的时候有 pending 状态,最后的信息才为 pending
|
|
355
|
+
if (receivingMessage && isLatest && isLatestItem){
|
|
356
|
+
status = 'pending'
|
|
329
357
|
}
|
|
330
358
|
|
|
331
|
-
const resultItem:
|
|
359
|
+
const resultItem: CustomThoughtChainItem = {
|
|
332
360
|
title: <div style={{display:"flex", flexDirection: 'row', alignItems: 'center'}}>
|
|
333
361
|
{getAvatarByName(name)}
|
|
334
362
|
<span>{name}</span>
|
|
@@ -373,7 +401,7 @@ export default function ChatMessage({
|
|
|
373
401
|
};
|
|
374
402
|
return resultItem
|
|
375
403
|
});
|
|
376
|
-
return <
|
|
404
|
+
return <CustomThoughtChain items={items} size={'small'} />
|
|
377
405
|
}
|
|
378
406
|
|
|
379
407
|
const renderBotFormMessage = (form_config) => {
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* URL卡片样式定义
|
|
5
|
+
* 用于展示可点击的应用卡片
|
|
6
|
+
*/
|
|
7
|
+
export const cardStyle= `
|
|
8
|
+
.boxUrlCard{
|
|
9
|
+
display: inline-block;
|
|
10
|
+
}
|
|
11
|
+
.section_1 {
|
|
12
|
+
background: linear-gradient( 221deg, #EFEEFF 0%, #F9F9FF 100%);
|
|
13
|
+
border-radius: 12px;
|
|
14
|
+
cursor: pointer;
|
|
15
|
+
display: flex;
|
|
16
|
+
align-items: center;
|
|
17
|
+
flex-direction: column;
|
|
18
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
19
|
+
padding: 12px;
|
|
20
|
+
}
|
|
21
|
+
.image-text_2 {
|
|
22
|
+
width: 100%;
|
|
23
|
+
padding: 0 12px 0 12px;
|
|
24
|
+
display: flex;
|
|
25
|
+
align-items: center;
|
|
26
|
+
}
|
|
27
|
+
.image_1 {
|
|
28
|
+
width: 45px;
|
|
29
|
+
height: 45px;
|
|
30
|
+
border-radius: 12px;
|
|
31
|
+
}
|
|
32
|
+
.text-group_3 {
|
|
33
|
+
margin-left: 12px;
|
|
34
|
+
display: flex;
|
|
35
|
+
flex-direction: column;
|
|
36
|
+
justify-content: space-between;
|
|
37
|
+
}
|
|
38
|
+
.text_2 {
|
|
39
|
+
overflow-wrap: break-word;
|
|
40
|
+
color: rgba(0, 0, 0, 1);
|
|
41
|
+
font-size: 16px;
|
|
42
|
+
font-family: PingFangSC-Medium, sans-serif;
|
|
43
|
+
font-weight: 500;
|
|
44
|
+
text-align: left;
|
|
45
|
+
white-space: nowrap;
|
|
46
|
+
margin-buttom: 8px;
|
|
47
|
+
}
|
|
48
|
+
.text_3 {
|
|
49
|
+
overflow-wrap: break-word;
|
|
50
|
+
color: #4C50FF;
|
|
51
|
+
font-size: 14px;
|
|
52
|
+
font-family: PingFangSC-Regular, sans-serif;
|
|
53
|
+
font-weight: normal;
|
|
54
|
+
text-align: left;
|
|
55
|
+
white-space: nowrap;
|
|
56
|
+
}
|
|
57
|
+
.line{
|
|
58
|
+
width: 100%;
|
|
59
|
+
height: 1.5px;
|
|
60
|
+
background-color: #D0D5FE;
|
|
61
|
+
margin: 12px 0;
|
|
62
|
+
}
|
|
63
|
+
.group_2 {
|
|
64
|
+
width: 80px;
|
|
65
|
+
height: 16px;
|
|
66
|
+
overflow-wrap: break-word;
|
|
67
|
+
color: rgba(76, 80, 255, 1);
|
|
68
|
+
font-size: 20px;
|
|
69
|
+
font-family: PingFangSC-Medium, sans-serif;
|
|
70
|
+
font-weight: 500;
|
|
71
|
+
text-align: left;
|
|
72
|
+
white-space: nowrap;
|
|
73
|
+
line-height: 15px;
|
|
74
|
+
}
|
|
75
|
+
.image-text_3 {
|
|
76
|
+
display: flex;
|
|
77
|
+
align-items: center;
|
|
78
|
+
justify-content: space-between;
|
|
79
|
+
}
|
|
80
|
+
.text-group_2 {
|
|
81
|
+
overflow-wrap: break-word;
|
|
82
|
+
color: rgba(76, 80, 255, 1);
|
|
83
|
+
font-size: 14px;
|
|
84
|
+
font-family: PingFangSC-Medium, sans-serif;
|
|
85
|
+
font-weight: 500;
|
|
86
|
+
text-align: left;
|
|
87
|
+
white-space: nowrap;
|
|
88
|
+
}
|
|
89
|
+
.thumbnail_1 {
|
|
90
|
+
width: 10px;
|
|
91
|
+
height: 12px;
|
|
92
|
+
margin-left: 8px;
|
|
93
|
+
}
|
|
94
|
+
`
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* URL卡片属性接口
|
|
98
|
+
*/
|
|
99
|
+
export type UrlCardProps = {
|
|
100
|
+
menuName: string; // 卡片标题
|
|
101
|
+
appName: string; // 应用名称
|
|
102
|
+
url: string; // 点击跳转的URL
|
|
103
|
+
iconUrl?: string; // 可选的图标URL
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* URL卡片组件
|
|
108
|
+
* 用于展示可点击的应用链接卡片
|
|
109
|
+
* @param props 组件属性
|
|
110
|
+
* @returns React组件
|
|
111
|
+
*/
|
|
112
|
+
export const UrlCard= ({
|
|
113
|
+
menuName,
|
|
114
|
+
appName,
|
|
115
|
+
url,
|
|
116
|
+
iconUrl = "https://trans-from-yuntu-resourse.oss-cn-beijing.aliyuncs.com/kai_yuan/common/card_header.png"
|
|
117
|
+
}: UrlCardProps) => {
|
|
118
|
+
return (
|
|
119
|
+
<div className="boxUrlCard" onClick={() => window.open(url, '_blank')}>
|
|
120
|
+
<div className="section_1">
|
|
121
|
+
<div className="image-text_2">
|
|
122
|
+
<img
|
|
123
|
+
className="image_1"
|
|
124
|
+
referrerPolicy="no-referrer"
|
|
125
|
+
src={iconUrl}
|
|
126
|
+
alt={appName}
|
|
127
|
+
/>
|
|
128
|
+
<div className="text-group_3">
|
|
129
|
+
<span className="text_2">{menuName}</span>
|
|
130
|
+
<span className="text_3">{appName}</span>
|
|
131
|
+
</div>
|
|
132
|
+
</div>
|
|
133
|
+
<div className="line"/>
|
|
134
|
+
<div className="image-text_3">
|
|
135
|
+
<span className="text-group_2">立即办理</span>
|
|
136
|
+
<img
|
|
137
|
+
className="thumbnail_1"
|
|
138
|
+
referrerPolicy="no-referrer"
|
|
139
|
+
src="https://trans-from-yuntu-resourse.oss-cn-beijing.aliyuncs.com/kai_yuan/common/arrow.png"
|
|
140
|
+
alt="箭头"
|
|
141
|
+
/>
|
|
142
|
+
</div>
|
|
143
|
+
</div>
|
|
144
|
+
</div>
|
|
145
|
+
)
|
|
146
|
+
}
|
|
@@ -1125,7 +1125,7 @@ export default function ChatWindow({
|
|
|
1125
1125
|
alt="Image"
|
|
1126
1126
|
/>
|
|
1127
1127
|
</div>
|
|
1128
|
-
<div className="w_tagItemText" style={isMobile ? {wordBreak: "keep-all"} : {}}>{item?.name}</div>
|
|
1128
|
+
<div className="w_tagItemText" style={isMobile ? {wordBreak: "keep-all", whiteSpace: "nowrap",} : {}}>{item?.name}</div>
|
|
1129
1129
|
</div>
|
|
1130
1130
|
))
|
|
1131
1131
|
}
|
|
@@ -3,6 +3,8 @@ import { useRef, useState } from 'react';
|
|
|
3
3
|
import ChatWindow from './chatWindow';
|
|
4
4
|
import { ChatMessageType } from './chatWindow/types/chatWidget';
|
|
5
5
|
import { styles, yt_style, markdownBody } from "./style"
|
|
6
|
+
import { customThoughtChainStyle } from "./chatWindow/chatMessage/CustomThoughtChain"
|
|
7
|
+
import { cardStyle } from "./chatWindow/chatMessage/urlCard"
|
|
6
8
|
|
|
7
9
|
export default function ChatWidget({
|
|
8
10
|
is_enable_call,
|
|
@@ -115,7 +117,7 @@ export default function ChatWidget({
|
|
|
115
117
|
|
|
116
118
|
return (
|
|
117
119
|
<div style={{ position: 'relative',height:'100%' }}>
|
|
118
|
-
<style dangerouslySetInnerHTML={{ __html: styles + markdownBody + yt_style }}></style>
|
|
120
|
+
<style dangerouslySetInnerHTML={{ __html: styles + markdownBody + yt_style + customThoughtChainStyle + cardStyle }}></style>
|
|
119
121
|
<div style={{fontSize: 10, color: '#a3a3a3', position: 'absolute', bottom: 6, width: '100%', display: 'flex', justifyContent: 'center'}}>内容由AI生成,无法保证真实准确,仅供参考</div>
|
|
120
122
|
<ChatWindow
|
|
121
123
|
is_enable_call={is_enable_call}
|