yt-chat-components 1.3.7 → 1.3.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.
- package/package.json +1 -1
- package/src/YtChatView/chatWidget/chatWindow/chatMessage/index.tsx +52 -22
- package/src/YtChatView/chatWidget/chatWindow/chatMessage/urlCard.tsx +148 -0
- package/src/YtChatView/chatWidget/chatWindow/index.tsx +1 -1
- package/src/YtChatView/chatWidget/chatWindow/types/chatWidget/index.ts +2 -1
package/package.json
CHANGED
|
@@ -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';
|
|
@@ -22,7 +22,7 @@ import type {ThoughtChainItem} from '@ant-design/x';
|
|
|
22
22
|
import {ThoughtChain} from '@ant-design/x';
|
|
23
23
|
import {CheckCircleOutlined, EllipsisOutlined, InfoCircleOutlined, ClockCircleOutlined} from '@ant-design/icons';
|
|
24
24
|
import ChatMessagePlaceholder, {ChatMessagePlaceholderInThought} from "../chatPlaceholder";
|
|
25
|
-
|
|
25
|
+
import {UrlCard} from "./urlCard"
|
|
26
26
|
let speechSynth = window.speechSynthesis;
|
|
27
27
|
let utterance = null;
|
|
28
28
|
|
|
@@ -231,26 +231,42 @@ export default function ChatMessage({
|
|
|
231
231
|
|
|
232
232
|
const renderLoading = (type:MessageType, height:number) => {
|
|
233
233
|
const skeletonContainerId = `skeleton-container-${Math.random().toString(36).substring(2, 9)}`;
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
// 其他类型暂不处理
|
|
242
|
-
(type == MessageType.echart || type == MessageType.form) && (
|
|
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,6 +300,23 @@ 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 (
|
|
314
|
+
<UrlCard url={form_url} appName={app_name} menuName={form_name}/>
|
|
315
|
+
)
|
|
316
|
+
} catch (error) {
|
|
317
|
+
return renderLoading(MessageType.url, 50);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
287
320
|
// 默认渲染其他代码块
|
|
288
321
|
return <code className={className} {...props}>{children}</code>;
|
|
289
322
|
},
|
|
@@ -318,14 +351,11 @@ export default function ChatMessage({
|
|
|
318
351
|
const renderBotTextMessage = () => {
|
|
319
352
|
const items = messageItemList.map((item, index) => {
|
|
320
353
|
const {id, thinkMessage, message, loadingMessage, type, name, toolCallInfo, rawInfo} = item;
|
|
321
|
-
const isLatest = index
|
|
354
|
+
const isLatest = index === messageItemList.length - 1;
|
|
322
355
|
let status = 'success'
|
|
323
|
-
// 只有在接收信息的时候有 pending
|
|
356
|
+
// 只有在接收信息的时候有 pending 状态,最后的信息才为 pending
|
|
324
357
|
if (receivingMessage && isLatest){
|
|
325
|
-
|
|
326
|
-
if(isLatest){
|
|
327
|
-
status = 'pending'
|
|
328
|
-
}
|
|
358
|
+
status = 'pending'
|
|
329
359
|
}
|
|
330
360
|
|
|
331
361
|
const resultItem: ThoughtChainItem = {
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import {ChatMessageType} from "../types/chatWidget";
|
|
2
|
+
import React from "react";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* URL卡片样式定义
|
|
6
|
+
* 用于展示可点击的应用卡片
|
|
7
|
+
*/
|
|
8
|
+
const cardStyle= `
|
|
9
|
+
.boxUrlCard{
|
|
10
|
+
display: inline-block;
|
|
11
|
+
}
|
|
12
|
+
.section_1 {
|
|
13
|
+
background: linear-gradient( 221deg, #EFEEFF 0%, #F9F9FF 100%);
|
|
14
|
+
border-radius: 12px;
|
|
15
|
+
cursor: pointer;
|
|
16
|
+
display: flex;
|
|
17
|
+
align-items: center;
|
|
18
|
+
flex-direction: column;
|
|
19
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
20
|
+
padding: 12px;
|
|
21
|
+
}
|
|
22
|
+
.image-text_2 {
|
|
23
|
+
width: 100%;
|
|
24
|
+
padding: 0 12px 0 12px;
|
|
25
|
+
display: flex;
|
|
26
|
+
align-items: center;
|
|
27
|
+
}
|
|
28
|
+
.image_1 {
|
|
29
|
+
width: 45px;
|
|
30
|
+
height: 45px;
|
|
31
|
+
border-radius: 12px;
|
|
32
|
+
}
|
|
33
|
+
.text-group_3 {
|
|
34
|
+
margin-left: 12px;
|
|
35
|
+
display: flex;
|
|
36
|
+
flex-direction: column;
|
|
37
|
+
justify-content: space-between;
|
|
38
|
+
}
|
|
39
|
+
.text_2 {
|
|
40
|
+
overflow-wrap: break-word;
|
|
41
|
+
color: rgba(0, 0, 0, 1);
|
|
42
|
+
font-size: 16px;
|
|
43
|
+
font-family: PingFangSC-Medium, sans-serif;
|
|
44
|
+
font-weight: 500;
|
|
45
|
+
text-align: left;
|
|
46
|
+
white-space: nowrap;
|
|
47
|
+
margin-buttom: 8px;
|
|
48
|
+
}
|
|
49
|
+
.text_3 {
|
|
50
|
+
overflow-wrap: break-word;
|
|
51
|
+
color: #4C50FF;
|
|
52
|
+
font-size: 14px;
|
|
53
|
+
font-family: PingFangSC-Regular, sans-serif;
|
|
54
|
+
font-weight: normal;
|
|
55
|
+
text-align: left;
|
|
56
|
+
white-space: nowrap;
|
|
57
|
+
}
|
|
58
|
+
.line{
|
|
59
|
+
width: 100%;
|
|
60
|
+
height: 1.5px;
|
|
61
|
+
background-color: #D0D5FE;
|
|
62
|
+
margin: 12px 0;
|
|
63
|
+
}
|
|
64
|
+
.group_2 {
|
|
65
|
+
width: 80px;
|
|
66
|
+
height: 16px;
|
|
67
|
+
overflow-wrap: break-word;
|
|
68
|
+
color: rgba(76, 80, 255, 1);
|
|
69
|
+
font-size: 20px;
|
|
70
|
+
font-family: PingFangSC-Medium, sans-serif;
|
|
71
|
+
font-weight: 500;
|
|
72
|
+
text-align: left;
|
|
73
|
+
white-space: nowrap;
|
|
74
|
+
line-height: 15px;
|
|
75
|
+
}
|
|
76
|
+
.image-text_3 {
|
|
77
|
+
display: flex;
|
|
78
|
+
align-items: center;
|
|
79
|
+
justify-content: space-between;
|
|
80
|
+
}
|
|
81
|
+
.text-group_2 {
|
|
82
|
+
overflow-wrap: break-word;
|
|
83
|
+
color: rgba(76, 80, 255, 1);
|
|
84
|
+
font-size: 14px;
|
|
85
|
+
font-family: PingFangSC-Medium, sans-serif;
|
|
86
|
+
font-weight: 500;
|
|
87
|
+
text-align: left;
|
|
88
|
+
white-space: nowrap;
|
|
89
|
+
}
|
|
90
|
+
.thumbnail_1 {
|
|
91
|
+
width: 10px;
|
|
92
|
+
height: 12px;
|
|
93
|
+
margin-left: 8px;
|
|
94
|
+
}
|
|
95
|
+
`
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* URL卡片属性接口
|
|
99
|
+
*/
|
|
100
|
+
export type UrlCardProps = {
|
|
101
|
+
menuName: string; // 卡片标题
|
|
102
|
+
appName: string; // 应用名称
|
|
103
|
+
url: string; // 点击跳转的URL
|
|
104
|
+
iconUrl?: string; // 可选的图标URL
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* URL卡片组件
|
|
109
|
+
* 用于展示可点击的应用链接卡片
|
|
110
|
+
* @param props 组件属性
|
|
111
|
+
* @returns React组件
|
|
112
|
+
*/
|
|
113
|
+
export const UrlCard= ({
|
|
114
|
+
menuName,
|
|
115
|
+
appName,
|
|
116
|
+
url,
|
|
117
|
+
iconUrl = "https://trans-from-yuntu-resourse.oss-cn-beijing.aliyuncs.com/kai_yuan/common/card_header.png"
|
|
118
|
+
}: UrlCardProps) => {
|
|
119
|
+
return (
|
|
120
|
+
<div className="boxUrlCard" onClick={() => window.open(url, '_blank')}>
|
|
121
|
+
<style dangerouslySetInnerHTML={{ __html: cardStyle }}></style>
|
|
122
|
+
<div className="section_1">
|
|
123
|
+
<div className="image-text_2">
|
|
124
|
+
<img
|
|
125
|
+
className="image_1"
|
|
126
|
+
referrerPolicy="no-referrer"
|
|
127
|
+
src={iconUrl}
|
|
128
|
+
alt={appName}
|
|
129
|
+
/>
|
|
130
|
+
<div className="text-group_3">
|
|
131
|
+
<span className="text_2">{menuName}</span>
|
|
132
|
+
<span className="text_3">{appName}</span>
|
|
133
|
+
</div>
|
|
134
|
+
</div>
|
|
135
|
+
<div className="line"/>
|
|
136
|
+
<div className="image-text_3">
|
|
137
|
+
<span className="text-group_2">立即办理</span>
|
|
138
|
+
<img
|
|
139
|
+
className="thumbnail_1"
|
|
140
|
+
referrerPolicy="no-referrer"
|
|
141
|
+
src="https://trans-from-yuntu-resourse.oss-cn-beijing.aliyuncs.com/kai_yuan/common/arrow.png"
|
|
142
|
+
alt="箭头"
|
|
143
|
+
/>
|
|
144
|
+
</div>
|
|
145
|
+
</div>
|
|
146
|
+
</div>
|
|
147
|
+
)
|
|
148
|
+
}
|
|
@@ -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
|
}
|