yt-chat-components 1.0.0 → 1.0.2

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.
Files changed (42) hide show
  1. package/.idea/modules.xml +1 -1
  2. package/.idea/sonarlint/issuestore/index.pb +3 -31
  3. package/dist/build/static/js/bundle.min.js +1 -0
  4. package/package.json +76 -76
  5. package/public/index.html +108 -108
  6. package/src/YtChatView/chatWidget/chatWindow/chatMessage/index.tsx +464 -464
  7. package/src/YtChatView/chatWidget/chatWindow/controllers/index.ts +249 -249
  8. package/src/YtChatView/chatWidget/chatWindow/index.module.css +196 -196
  9. package/src/YtChatView/chatWidget/chatWindow/index.tsx +1054 -1041
  10. package/src/YtChatView/chatWidget/chatWindow/types/chatWidget/index.ts +50 -50
  11. package/src/YtChatView/chatWidget/index.tsx +2586 -2586
  12. package/src/YtChatView/logoBtn/index.css +3 -3
  13. package/src/YtChatView/logoBtn/index.jsx +103 -103
  14. package/src/YtChatView/logoSplitBtn/index.css +3 -3
  15. package/src/YtChatView/logoSplitBtn/index.jsx +105 -105
  16. package/src/YtChatView/mobileChat/index.jsx +944 -848
  17. package/src/YtChatView/mobileChat/index.module.css +253 -253
  18. package/src/YtChatView/previewDialog/index.jsx +600 -600
  19. package/src/YtChatView/previewDialog/index.module.css +253 -253
  20. package/src/chatWidget/chatWindow/index.tsx +426 -426
  21. package/src/chatWidget/index.tsx +2193 -2193
  22. package/src/index.tsx +10 -10
  23. package/webpack.config.js +50 -50
  24. package/.idea/sonarlint/issuestore/3/6/364385cedcce4c06de1901392ffeeac0caef0f3c +0 -0
  25. package/.idea/sonarlint/issuestore/3/9/39129446b425a1d640160c068e4194e96639eedf +0 -0
  26. package/.idea/sonarlint/issuestore/4/a/4a2f33951ce07c1ff7184f91877aa13db05d3785 +0 -0
  27. package/.idea/sonarlint/issuestore/4/a/4a7b99bdbee5792679d347b6474463bf5e14b66d +0 -0
  28. package/.idea/sonarlint/issuestore/4/b/4b015aa5428c4d4c3d672893ec23f5fe3969f9be +0 -0
  29. package/.idea/sonarlint/issuestore/4/b/4b6989b8ccae808ebc45d02230d336ea53800365 +0 -0
  30. package/.idea/sonarlint/issuestore/6/1/61ebb9fd6e8cf9082658121d5d81e297791dacd0 +0 -0
  31. package/.idea/sonarlint/issuestore/6/c/6c024c1d0ad64656b9d4b0695ec3c49c0454addf +0 -0
  32. package/.idea/sonarlint/issuestore/6/e/6e75fc1c07c3a427a86fc213ca9479caaaff00ea +0 -0
  33. package/.idea/sonarlint/issuestore/8/d/8d6123af13a140f93e06299fff7ea23c547e9ec8 +0 -0
  34. package/.idea/sonarlint/issuestore/c/c/cc2352788140b6778ac06df4b33f50b390d2d8be +0 -0
  35. package/.idea/sonarlint/issuestore/d/5/d5595158cc48f9bf3e51b06f6e6805a8fd2d6262 +0 -0
  36. package/.idea/sonarlint/issuestore/d/7/d747cbed4201192dfa83a1a51345b020a050b647 +0 -0
  37. package/.idea/sonarlint/issuestore/d/9/d938938695d447dadda115e28781c6541f53fc4f +0 -0
  38. package/build/static/js/bundle.min.js +0 -2
  39. package/build/static/js/bundle.min.js.LICENSE.txt +0 -132
  40. /package/.idea/{langflow-embedded-chat.iml → langflow-embedded-chat-clone.iml} +0 -0
  41. /package/.idea/sonarlint/issuestore/{0/f/0f8c0c92cf798431ebb931ff6e997b1af86ecee5 → 7/0/7030d0b2f71b999ff89a343de08c414af32fc93a} +0 -0
  42. /package/.idea/sonarlint/issuestore/{2/7/27e69cb561aeea20c1afbdd32d260dd60b89a81b → 9/c/9cfff9a6d27bd6c255aa751213163c7901fb8ce7} +0 -0
@@ -1,600 +1,600 @@
1
- import React from 'react';
2
- import ChatWidget from '../chatWidget/index';
3
- import aiAvatarPng from '../../assets/aicenter/aiavatar.png';
4
- import historyPng from '../../assets/aicenter/history.png';
5
- import closePng from '../../assets/aicenter/close.png';
6
- import { getFlowInfo, getHistoryList, getSceneInfo } from '../chatWidget/chatWindow/controllers/index';
7
- import './index.module.css'
8
- import { v4 as uuidv4 } from 'uuid';
9
- import historyListEmptyPng from '../../assets/aicenter/history-list-empty.png';
10
- import addPng from '../../assets/aicenter/add.png';
11
- import {isEmpty, isFunction} from "lodash";
12
- import { Button, message as messageTip, Progress, Skeleton } from 'antd'
13
- import { CloseOutlined } from "@ant-design/icons";
14
- import moreAi from '../../assets/aicenter/moreAi.png';
15
- import moreBg from '../../assets/aicenter/moreBg.png';
16
- import self_knowledge from '../../assets/aicenter/self_knowledge.png';
17
- import self_skills from '../../assets/aicenter/self_skills.png';
18
-
19
-
20
- const style=`
21
- .p_closeImg {
22
- width: 14px;
23
- cursor: pointer;
24
- }
25
-
26
- .p_toolDialog {
27
- display: flex;
28
- height:100%;
29
- background:url('https://trans-from-yuntu-resourse.oss-cn-beijing.aliyuncs.com/smartSchool/appCreator/ai/ai_modal_bg.png');
30
- background-size: cover;
31
- border-radius:8px;
32
- }
33
-
34
- .p_toolDialog .p_toolLeft {
35
- display: flex;
36
- flex-direction: column;
37
- align-items: center;
38
- width: 300px;
39
- padding: 1.7rem 1.6rem 1.7rem 1.6rem;
40
-
41
- border-top-left-radius: 8px;
42
- border-bottom-left-radius: 8px;
43
- }
44
-
45
- .p_toolDialog .p_toolLeft .p_toolLogo {
46
- user-select: none;
47
- display: flex;
48
- align-items: center;
49
- }
50
-
51
- .p_toolDialog .p_toolLeft .p_toolLogo .p_logoImg {
52
- width: 48px;
53
- }
54
-
55
- .p_toolDialog .p_toolLeft .p_toolLogo .p_logoText {
56
- font-weight: bold;
57
- margin-left: 10px;
58
- font-size: 30px;
59
- background: linear-gradient(to right, #1551FF, #8F4BFF);
60
- -webkit-background-clip: text;
61
- -webkit-text-fill-color: transparent;
62
- }
63
-
64
- .p_toolDialog .p_toolLeft .p_historyDialog {
65
- user-select: none;
66
- margin-top: 20px;
67
- margin-bottom: 20px;
68
- border-radius: 10px;
69
- flex: 1;
70
- width: 100%;
71
- background: linear-gradient(180deg, rgba(255, 255, 255, 0.5) 0%, rgba(255, 255, 255, 0) 100%);
72
- border-image: linear-gradient(180deg, rgba(255, 255, 255, 1), rgba(255, 255, 255, 0)) 1 1;
73
- backdrop-filter: blur(10px);
74
- position: relative;
75
- max-height:calc(100% - 5.5rem - 60px);
76
- }
77
-
78
- .p_toolDialog .p_toolLeft .p_historyDialog ::-webkit-scrollbar-thumb {
79
- border-radius: 10px;
80
- -webkit-box-shadow: inset 0 0 5px rgba(0,0,0,0.2);
81
- background: #535353 !important;
82
- }
83
-
84
- .p_toolDialog .p_toolLeft .p_historyDialog .p_historyTitle {
85
- padding: 1.3rem 16px 0 16px;
86
- display: flex;
87
- align-items: center;
88
- }
89
-
90
- .p_toolDialog .p_toolLeft .p_historyDialog .p_historyTitle .p_historyImg {
91
- width: 25px;
92
- }
93
-
94
- .p_toolDialog .p_toolLeft .p_historyDialog .p_historyTitle .p_dialogTitle {
95
- margin-left: 10px;
96
- font-weight: 500;
97
- font-size: 18px;
98
- color: #333333;
99
- line-height: 16px;
100
- text-align: left;
101
- font-style: normal;
102
- }
103
-
104
- .p_toolDialog .p_toolLeft .p_historyDialog .p_historyListEmpty {
105
- position: absolute;
106
- top: 50%;
107
- left: 50%;
108
- transform: translate(-50%, -50%);
109
- text-align: center;
110
- font-size: 12px;
111
- color: #999999;
112
- max-height: calc(100% - 3rem);
113
-
114
- }
115
-
116
- .p_toolDialog .p_toolLeft .p_historyDialog .p_historyList {
117
- height: calc(100% - 3rem);
118
- margin-top: 10px;
119
- overflow-y: auto;
120
- scrollbar-width: none !important; /* firefox */
121
- }
122
-
123
- .p_toolDialog .p_toolLeft .p_historyDialog .p_historyList::-webkit-scrollbar{
124
- display:none;
125
- }
126
-
127
- .p_toolDialog .p_toolLeft .p_historyDialog .p_historyList:hover {
128
- scrollbar-width: thin !important; /* firefox */
129
- scrollbar-color: #ced4e3 transparent;
130
- }
131
-
132
- .p_toolDialog .p_toolLeft .p_historyDialog .p_historyList .p_historyItem {
133
- padding: 7px 16px;
134
- }
135
-
136
- .p_toolDialog .p_toolLeft .p_historyDialog .p_historyList .p_historyItem .p_activeHistoryName {
137
- color: #1552FF !important;
138
- }
139
-
140
- .p_toolDialog .p_toolLeft .p_historyDialog .p_historyList .p_historyItem .p_historyName {
141
- color: #333333;
142
- overflow: hidden;
143
- text-overflow: ellipsis;
144
- white-space: nowrap;
145
- cursor: pointer;
146
- }
147
-
148
- .p_toolDialog .p_toolLeft .p_historyDialog .p_historyList .p_historyItem .p_historyName:hover {
149
- color: #171717;
150
- }
151
-
152
- .p_toolDialog .p_toolRight {
153
- flex: 1;
154
- }
155
-
156
- .p_toolRightToRight {
157
- width:300px;
158
- display:flex;
159
- flex-direction:column;
160
- padding:2rem 1.6rem 1.8rem 1.6rem
161
- }
162
- .rightInnerContainer{
163
- height:calc(100% - 80px);
164
- flex:1;
165
- display:flex;
166
- flex-direction:column;
167
- justify-content: space-between;
168
- }
169
- .p_toolRightToRight .rightSideTitle{
170
- margin-bottom:1.4rem;
171
- margin-top:10px;
172
- margin-top:0;
173
- font-size:18px;
174
- font-weight:500;
175
- display:flex;
176
- align-items: center;
177
- }
178
- .p_toolRightToRight .rightSideTitle img{
179
- margin-right:4px;
180
- }
181
-
182
- .p_toolRightToRight .rightSideTitle .titleSideColumn{
183
- color:#1551FF;
184
- }
185
-
186
- .p_toolRightToRight .rightSkillContainer{
187
- min-height:40%;
188
- }
189
- .p_toolRightToRight .rightSkillContainer .rightSkillList{
190
- display: flex;
191
- flex-wrap: wrap;
192
- grid-template-columns: repeat(3, 1fr);
193
- gap: 10px;
194
- }
195
- .p_toolRightToRight .rightSkillContainer .rightSkillList .rightSkillItem{
196
- text-align: center;
197
- cursor:pointer;
198
- width:30%;
199
- }
200
- .p_toolRightToRight .rightSkillContainer .rightSkillList .rightSkillItem img{
201
- width: 40px;
202
- height: 40px;
203
- border-radius:10px;
204
- }
205
- .p_toolRightToRight .rightSkillContainer .rightSkillList .rightSkillItem p{
206
- margin-top:0px;
207
- margin-bottom:4px;
208
- overflow: hidden;
209
- text-overflow: ellipsis;
210
- white-space: nowrap;
211
- color: #333333;
212
- }
213
- .p_toolRightToRight .rightKnowledgeTitle{
214
- nargin-top: 2.2rem;
215
- margin-bottom: 1.4rem;
216
- font-size:18px;
217
- font-weight:500;
218
- display:flex;
219
- align-items: center;
220
- }
221
-
222
- .p_toolRightToRight .rightKnowledgeTitle img{
223
- margin-right:4px;
224
- }
225
-
226
- .p_toolRightToRight .rightKnowledgeContainer{
227
- position:relative;
228
- }
229
- .p_toolRightToRight .rightMoreButton{
230
- background: url(${moreAi});
231
- background-size: 85% auto;
232
- background-repeat: no-repeat;
233
- background-position: bottom;
234
- position: absolute;
235
- bottom: 8px;
236
- left: 0;
237
- width: 100%;
238
- height: 100%;
239
- z-index: 1;
240
- display: flex;
241
- justify-content: center;
242
- align-items: flex-end;
243
- }
244
- .p_toolRightToRight .rightMoreButton div{
245
- width:calc(100% - 50px);
246
- padding: 16px 16px 10px 20px;
247
- font-weight: 500;
248
- color: #ffffff;
249
- line-height: 17px;
250
- font-size: 12px;
251
- cursor:pointer;
252
- }
253
-
254
- .p_newDialog {
255
- width: 252px;
256
- height: 40px;
257
- min-height:40px;
258
- background: linear-gradient( 45deg, #1551FF 0%, #8F4BFF 100%);
259
- margin-top: 20px;
260
- border-radius: 20px;
261
- cursor: pointer;
262
- display: flex;
263
- align-items: center;
264
- justify-content: center;
265
- }
266
-
267
- .p_newDialog img {
268
- width: 18px;
269
- }
270
-
271
- .p_newDialog .p_newDialogText {
272
- color: #fff;
273
- margin-left: 6px;
274
- }
275
- `
276
-
277
- const defaultList = [
278
- {
279
- backgroundImg: 'https://trans-from-yuntu-resourse.oss-cn-beijing.aliyuncs.com/smartSchool/appCreator/ai/drop-down-item-card-01.png',
280
- title: '我这学期的课程安排是什么样?',
281
- },
282
- {
283
- backgroundImg: 'https://trans-from-yuntu-resourse.oss-cn-beijing.aliyuncs.com/smartSchool/appCreator/ai/drop-down-item-card-02.png',
284
- title: '我上个学期的成绩是多少?',
285
- },
286
- {
287
- backgroundImg: 'https://trans-from-yuntu-resourse.oss-cn-beijing.aliyuncs.com/smartSchool/appCreator/ai/drop-down-item-card-03.png',
288
- title: '哪里可以找到心理咨询服务?',
289
- },
290
- ];
291
-
292
- const formatFileSize = (bytes) => {
293
- // 如果字节数为0,直接返回
294
- if(isEmpty(bytes)) {
295
- return { formattedSize: 0, unit: 'B' };
296
- }
297
- if(bytes === 0) return { formattedSize: 0, unit: 'B' };
298
-
299
- // 定义单位和对应的字节数(1024进制)
300
- const units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
301
- // 计算合适的单位索引
302
- const index = Math.floor(Math.log(bytes) / Math.log(1024));
303
- // 将字节数转换为目标单位
304
- const size = bytes / Math.pow(1024, index);
305
- // 保留两位小数,并去除多余的0
306
- const formattedSize = size.toFixed(2).replace(/\.?0+$/, '');
307
- return { formattedSize, unit: units[index] }
308
- }
309
-
310
-
311
- const api_key = 'sk-mniUFDpcWwvNF3iFzssXa6etN-S_Y4AApyHYcBU44L0';
312
-
313
-
314
- export class ToolDialog extends React.Component {
315
- state = {
316
- historyList: [], // 历史对话列表
317
- sessionId: uuidv4(), // 当前激活的对话对应的sessionId
318
- dropDownList: [],
319
- sceneInfo: {},
320
- currentFlow: {},
321
- };
322
-
323
- async componentDidMount() {
324
- if(isEmpty(this.props.sceneId)){
325
- // 兼容非场景打开的情况
326
- this.getHistoryList({},true);
327
- }else{
328
- const sceneData = await this.getSceneInfo();
329
- if(isEmpty(sceneData)) {
330
- this.getHistoryList({},true);
331
- } else {
332
- this.getHistoryList(sceneData,true);
333
- }
334
- }
335
- }
336
-
337
- getCurrentFlowHistory=(flowId)=>{
338
- let { userInfo = {} } = this.props;
339
- const { sessionId } = this.state;
340
- if(isEmpty(userInfo.code)) {
341
- userInfo.code = sessionId;
342
- }
343
- const operationId = userInfo['code'] || '';
344
- getHistoryList(this.props.hostUrl, flowId, operationId).then((res) => {
345
- if(res.status === 200){
346
- this.setState({ historyList: res.data });
347
- }
348
- });
349
- }
350
-
351
- // 获取历史对话列表
352
- getHistoryList = (sceneData, isRefreshWords) => {
353
- const { sceneId, appId: flowId, isShowSideLeft } = this.props;
354
- if(isEmpty(sceneId)){
355
- // 单独组件情况
356
- if(isRefreshWords){
357
- this.getFlowInfo().then(currentFlow=>{
358
- const dropDownList = this.getDropDownList(currentFlow?.welcome_words||[]);
359
- this.setState({ dropDownList, currentFlow })
360
- })
361
- }
362
- if(isShowSideLeft) {
363
- this.getCurrentFlowHistory(flowId)
364
- }
365
- }else{
366
- const currentScene = sceneData||this.state.sceneInfo;
367
- const currentFlow = currentScene.flows[0];
368
- const dropDownList = this.getDropDownList(currentFlow?.welcome_words||[]);
369
- if(!isEmpty(sceneData)){
370
- this.setState({ currentFlow, dropDownList })
371
- }else if(isEmpty(this.state.sceneInfo)){
372
- this.setState({ dropDownList:defaultList })
373
- }
374
- if(isShowSideLeft) {
375
- this.getCurrentFlowHistory(currentFlow.id)
376
- }
377
- }
378
- };
379
-
380
- getSceneInfo = async ()=>{
381
- const res = await getSceneInfo(this.props.hostUrl, this.props.sceneId, api_key);
382
- if(res.status === 200){
383
- this.setState({ sceneInfo: res.data });
384
- }
385
- return res.data;
386
- }
387
-
388
- getFlowInfo = async () => {
389
- const res = await getFlowInfo(this.props.hostUrl, this.props.appId, api_key);
390
- if(res.status === 200) {
391
- this.setState({ sceneInfo: res.data });
392
- }
393
- return res.data;
394
- }
395
-
396
- // 新建对话
397
- newDialog = () => {
398
- if(this.state.dropDownList) {
399
- messageTip.info("当前已是最新对话")
400
- return;
401
- }
402
- this.setState({ sessionId: uuidv4() });
403
- this.setState({ dropDownList: this.getDropDownList(this.state.currentFlow?.welcome_words||[]) })
404
- }
405
-
406
- updateSessionId = (sessionId) => {
407
- this.setState({ sessionId });
408
- };
409
-
410
- getDropDownList = (welcome_words)=>{
411
- if(isEmpty(welcome_words)){
412
- return defaultList;
413
- }
414
- return welcome_words.slice(0,3).map((question,index)=>(
415
- {
416
- backgroundImg:defaultList[index].backgroundImg,
417
- title:question,
418
- }
419
- ))
420
- }
421
-
422
- render() {
423
- const {
424
- title,
425
- appId: flowId,
426
- hostUrl,
427
- setDialogVisible,
428
- userInfo,
429
- boxStyle,
430
- isShowSideRight,
431
- isShowSideLeft = true,
432
- tags = [],
433
- agentUrl = aiAvatarPng,
434
- agentName = '校园智多星',
435
- logoWidth = '42px',
436
- logoFontSize = '26px',
437
- isTitleSideIcon = false,// 是否将左侧历史顶部icon移到中间顶部左侧蓝点位置
438
- modalIndex,
439
- isShowUploadButton,
440
- dropManUrl,
441
- modalWidth
442
- } = this.props;
443
- const { sceneInfo, currentFlow = {} } = this.state;
444
- const { flows = [], name: sceneName, character } = sceneInfo;
445
- return (
446
- <div style={boxStyle}>
447
- <style dangerouslySetInnerHTML={{ __html: style }}></style>
448
- <div style={{ position: 'absolute', top: '18px', right: '18px', zIndex: modalIndex }}>
449
- {isFunction(setDialogVisible) &&
450
- <img onClick={() => setDialogVisible(false)} className="p_closeImg" src={closePng}/>}
451
- </div>
452
- <div className="p_toolDialog">
453
- {
454
- isShowSideLeft && <div className="p_toolLeft">
455
- <div className="p_toolLogo">
456
- <img className="p_logoImg" style={{ width: logoWidth, borderRadius: 15 }} src={agentUrl}/>
457
- <div className="p_logoText" style={{ fontSize: logoFontSize }}>{agentName}</div>
458
- </div>
459
- <div className="p_historyDialog">
460
- <div className="p_historyTitle">
461
- <img className="p_historyImg" src={historyPng}/>
462
- <div className="p_dialogTitle">对话列表</div>
463
- </div>
464
- {this.state.historyList.length > 0 ? (
465
- <div className="p_historyList">
466
- {this.state.historyList?.map((item) => (
467
- <div
468
- key={item.session_id}
469
- className="p_historyItem"
470
- onClick={() => {
471
- this.setState({ dropDownList: undefined })
472
- this.updateSessionId(item.session_id);
473
- }}
474
- >
475
- <div
476
- className={`p_historyName ${
477
- item.session_id === this.state.sessionId ? 'p_activeHistoryName' : ''
478
- }`}
479
- >
480
- {item.text}
481
- </div>
482
- </div>
483
- ))}
484
- </div>
485
- ) : (
486
- <div className="p_historyListEmpty">
487
- <img src={historyListEmptyPng}/>
488
- <div className="p_historyListEmptyText">暂无对话记录</div>
489
- </div>
490
- )}
491
- </div>
492
- <div className="p_newDialog" onClick={() => {
493
- this.newDialog()
494
- }}>
495
- <img src={addPng}/>
496
- <div className="p_newDialogText">新建对话</div>
497
- </div>
498
- </div>
499
- }
500
- <div className="p_toolRight">
501
- <ChatWidget
502
- window_title={currentFlow?.name || title}
503
- flow_id={currentFlow?.id || flowId}
504
- tags={currentFlow?.keywords || tags}
505
- host_url={hostUrl}
506
- api_key={api_key}
507
- session_id={this.state.sessionId}
508
- userInfo={userInfo}
509
- getHistoryList={this.getHistoryList}
510
- setDropDownList={(list) => this.setState({ dropDownList: list })}
511
- dropDownList={this.state.dropDownList}
512
- baseConfig={{ isTitleSideIcon, logoWidth, agentUrl }}
513
- isShowUploadButton={isShowUploadButton}
514
- dropManUrl={character || dropManUrl}
515
- modalWidth={modalWidth}
516
- />
517
- </div>
518
- {
519
- isShowSideRight &&
520
- <div className={"p_toolRightToRight"}>
521
- <div className={"rightInnerContainer"}>
522
- <div>
523
- <h3 className={"rightSideTitle"}>
524
- <img width={15} src={self_skills}/>
525
- <span style={{ color: "#333333" }}>专项技能</span>
526
- </h3>
527
- {
528
- isEmpty(flows) ?
529
- <Skeleton
530
- title={false}
531
- active
532
- paragraph={{ rows: 5, width: '100%' }}
533
- />
534
- :
535
- <div className={"rightSkillContainer"}>
536
- <div className={"rightSkillList"}>
537
- {flows.slice(0, 12).map((item) => (
538
- <div className={"rightSkillItem"} key={item.id} onClick={() => {
539
- // 右侧点击一个技能,更新sessionId,切换当前flow信息,重新查询历史记录
540
- this.setState({
541
- sessionId: uuidv4(),
542
- currentFlow: item,
543
- dropDownList: this.getDropDownList(item?.welcome_words||[])
544
- });
545
- this.getCurrentFlowHistory(item.id);
546
- }}>
547
- <img
548
- src={item.icon}
549
- alt={item.name}/>
550
- <p>{item.name}</p>
551
- </div>
552
- ))}
553
- </div>
554
- </div>
555
- }
556
- </div>
557
- <div>
558
- <h3 className={"rightKnowledgeTitle"}>
559
- <img width={15} src={self_knowledge}/>
560
- <span style={{ color: "#333333" }}>个人知识库</span>
561
- </h3>
562
- {
563
- isEmpty(currentFlow) ?
564
- <Skeleton
565
- title={false}
566
- active
567
- paragraph={{ rows: 5, width: '100%' }}
568
- /> :
569
- <div className={"rightKnowledgeContainer"}>
570
- <img src={moreBg}/>
571
- <div style={{ position: 'absolute', top: '40px', left: '16px' }}>
572
- <div>文件总数<span style={{
573
- padding: 8,
574
- fontSize: '20px',
575
- fontWeight: 700
576
- }}>{currentFlow.k_count || 0}</span>个
577
- </div>
578
- <div style={{ marginTop: 10 }}>文件总量<span style={{
579
- padding: 8,
580
- fontSize: '20px',
581
- fontWeight: 700
582
- }}>{formatFileSize(currentFlow.k_size).formattedSize}</span>{formatFileSize(currentFlow.k_size).unit}
583
- </div>
584
- </div>
585
- <div className={"rightMoreButton"}>
586
- <div className={"rightMoreTitle"} onClick={() => messageTip.info("敬请期待")}>训练你的专属知识库</div>
587
- </div>
588
- </div>
589
- }
590
- </div>
591
- </div>
592
- </div>
593
- }
594
- </div>
595
- </div>
596
- );
597
- }
598
- }
599
-
600
- export default ToolDialog;
1
+ import React from 'react';
2
+ import ChatWidget from '../chatWidget/index';
3
+ import aiAvatarPng from '../../assets/aicenter/aiavatar.png';
4
+ import historyPng from '../../assets/aicenter/history.png';
5
+ import closePng from '../../assets/aicenter/close.png';
6
+ import { getFlowInfo, getHistoryList, getSceneInfo } from '../chatWidget/chatWindow/controllers/index';
7
+ import './index.module.css'
8
+ import { v4 as uuidv4 } from 'uuid';
9
+ import historyListEmptyPng from '../../assets/aicenter/history-list-empty.png';
10
+ import addPng from '../../assets/aicenter/add.png';
11
+ import {isEmpty, isFunction} from "lodash";
12
+ import { Button, message as messageTip, Progress, Skeleton } from 'antd'
13
+ import { CloseOutlined } from "@ant-design/icons";
14
+ import moreAi from '../../assets/aicenter/moreAi.png';
15
+ import moreBg from '../../assets/aicenter/moreBg.png';
16
+ import self_knowledge from '../../assets/aicenter/self_knowledge.png';
17
+ import self_skills from '../../assets/aicenter/self_skills.png';
18
+
19
+
20
+ const style=`
21
+ .p_closeImg {
22
+ width: 14px;
23
+ cursor: pointer;
24
+ }
25
+
26
+ .p_toolDialog {
27
+ display: flex;
28
+ height:100%;
29
+ background:url('https://trans-from-yuntu-resourse.oss-cn-beijing.aliyuncs.com/smartSchool/appCreator/ai/ai_modal_bg.png');
30
+ background-size: cover;
31
+ border-radius:8px;
32
+ }
33
+
34
+ .p_toolDialog .p_toolLeft {
35
+ display: flex;
36
+ flex-direction: column;
37
+ align-items: center;
38
+ width: 300px;
39
+ padding: 1.7rem 1.6rem 1.7rem 1.6rem;
40
+
41
+ border-top-left-radius: 8px;
42
+ border-bottom-left-radius: 8px;
43
+ }
44
+
45
+ .p_toolDialog .p_toolLeft .p_toolLogo {
46
+ user-select: none;
47
+ display: flex;
48
+ align-items: center;
49
+ }
50
+
51
+ .p_toolDialog .p_toolLeft .p_toolLogo .p_logoImg {
52
+ width: 48px;
53
+ }
54
+
55
+ .p_toolDialog .p_toolLeft .p_toolLogo .p_logoText {
56
+ font-weight: bold;
57
+ margin-left: 10px;
58
+ font-size: 30px;
59
+ background: linear-gradient(to right, #1551FF, #8F4BFF);
60
+ -webkit-background-clip: text;
61
+ -webkit-text-fill-color: transparent;
62
+ }
63
+
64
+ .p_toolDialog .p_toolLeft .p_historyDialog {
65
+ user-select: none;
66
+ margin-top: 20px;
67
+ margin-bottom: 20px;
68
+ border-radius: 10px;
69
+ flex: 1;
70
+ width: 100%;
71
+ background: linear-gradient(180deg, rgba(255, 255, 255, 0.5) 0%, rgba(255, 255, 255, 0) 100%);
72
+ border-image: linear-gradient(180deg, rgba(255, 255, 255, 1), rgba(255, 255, 255, 0)) 1 1;
73
+ backdrop-filter: blur(10px);
74
+ position: relative;
75
+ max-height:calc(100% - 5.5rem - 60px);
76
+ }
77
+
78
+ .p_toolDialog .p_toolLeft .p_historyDialog ::-webkit-scrollbar-thumb {
79
+ border-radius: 10px;
80
+ -webkit-box-shadow: inset 0 0 5px rgba(0,0,0,0.2);
81
+ background: #535353 !important;
82
+ }
83
+
84
+ .p_toolDialog .p_toolLeft .p_historyDialog .p_historyTitle {
85
+ padding: 1.3rem 16px 0 16px;
86
+ display: flex;
87
+ align-items: center;
88
+ }
89
+
90
+ .p_toolDialog .p_toolLeft .p_historyDialog .p_historyTitle .p_historyImg {
91
+ width: 25px;
92
+ }
93
+
94
+ .p_toolDialog .p_toolLeft .p_historyDialog .p_historyTitle .p_dialogTitle {
95
+ margin-left: 10px;
96
+ font-weight: 500;
97
+ font-size: 18px;
98
+ color: #333333;
99
+ line-height: 16px;
100
+ text-align: left;
101
+ font-style: normal;
102
+ }
103
+
104
+ .p_toolDialog .p_toolLeft .p_historyDialog .p_historyListEmpty {
105
+ position: absolute;
106
+ top: 50%;
107
+ left: 50%;
108
+ transform: translate(-50%, -50%);
109
+ text-align: center;
110
+ font-size: 12px;
111
+ color: #999999;
112
+ max-height: calc(100% - 3rem);
113
+
114
+ }
115
+
116
+ .p_toolDialog .p_toolLeft .p_historyDialog .p_historyList {
117
+ height: calc(100% - 3rem);
118
+ margin-top: 10px;
119
+ overflow-y: auto;
120
+ scrollbar-width: none !important; /* firefox */
121
+ }
122
+
123
+ .p_toolDialog .p_toolLeft .p_historyDialog .p_historyList::-webkit-scrollbar{
124
+ display:none;
125
+ }
126
+
127
+ .p_toolDialog .p_toolLeft .p_historyDialog .p_historyList:hover {
128
+ scrollbar-width: thin !important; /* firefox */
129
+ scrollbar-color: #ced4e3 transparent;
130
+ }
131
+
132
+ .p_toolDialog .p_toolLeft .p_historyDialog .p_historyList .p_historyItem {
133
+ padding: 7px 16px;
134
+ }
135
+
136
+ .p_toolDialog .p_toolLeft .p_historyDialog .p_historyList .p_historyItem .p_activeHistoryName {
137
+ color: #1552FF !important;
138
+ }
139
+
140
+ .p_toolDialog .p_toolLeft .p_historyDialog .p_historyList .p_historyItem .p_historyName {
141
+ color: #333333;
142
+ overflow: hidden;
143
+ text-overflow: ellipsis;
144
+ white-space: nowrap;
145
+ cursor: pointer;
146
+ }
147
+
148
+ .p_toolDialog .p_toolLeft .p_historyDialog .p_historyList .p_historyItem .p_historyName:hover {
149
+ color: #171717;
150
+ }
151
+
152
+ .p_toolDialog .p_toolRight {
153
+ flex: 1;
154
+ }
155
+
156
+ .p_toolRightToRight {
157
+ width:300px;
158
+ display:flex;
159
+ flex-direction:column;
160
+ padding:2rem 1.6rem 1.8rem 1.6rem
161
+ }
162
+ .rightInnerContainer{
163
+ height:calc(100% - 80px);
164
+ flex:1;
165
+ display:flex;
166
+ flex-direction:column;
167
+ justify-content: space-between;
168
+ }
169
+ .p_toolRightToRight .rightSideTitle{
170
+ margin-bottom:1.4rem;
171
+ margin-top:10px;
172
+ margin-top:0;
173
+ font-size:18px;
174
+ font-weight:500;
175
+ display:flex;
176
+ align-items: center;
177
+ }
178
+ .p_toolRightToRight .rightSideTitle img{
179
+ margin-right:4px;
180
+ }
181
+
182
+ .p_toolRightToRight .rightSideTitle .titleSideColumn{
183
+ color:#1551FF;
184
+ }
185
+
186
+ .p_toolRightToRight .rightSkillContainer{
187
+ min-height:40%;
188
+ }
189
+ .p_toolRightToRight .rightSkillContainer .rightSkillList{
190
+ display: flex;
191
+ flex-wrap: wrap;
192
+ grid-template-columns: repeat(3, 1fr);
193
+ gap: 10px;
194
+ }
195
+ .p_toolRightToRight .rightSkillContainer .rightSkillList .rightSkillItem{
196
+ text-align: center;
197
+ cursor:pointer;
198
+ width:30%;
199
+ }
200
+ .p_toolRightToRight .rightSkillContainer .rightSkillList .rightSkillItem img{
201
+ width: 40px;
202
+ height: 40px;
203
+ border-radius:10px;
204
+ }
205
+ .p_toolRightToRight .rightSkillContainer .rightSkillList .rightSkillItem p{
206
+ margin-top:0px;
207
+ margin-bottom:4px;
208
+ overflow: hidden;
209
+ text-overflow: ellipsis;
210
+ white-space: nowrap;
211
+ color: #333333;
212
+ }
213
+ .p_toolRightToRight .rightKnowledgeTitle{
214
+ nargin-top: 2.2rem;
215
+ margin-bottom: 1.4rem;
216
+ font-size:18px;
217
+ font-weight:500;
218
+ display:flex;
219
+ align-items: center;
220
+ }
221
+
222
+ .p_toolRightToRight .rightKnowledgeTitle img{
223
+ margin-right:4px;
224
+ }
225
+
226
+ .p_toolRightToRight .rightKnowledgeContainer{
227
+ position:relative;
228
+ }
229
+ .p_toolRightToRight .rightMoreButton{
230
+ background: url(${moreAi});
231
+ background-size: 85% auto;
232
+ background-repeat: no-repeat;
233
+ background-position: bottom;
234
+ position: absolute;
235
+ bottom: 8px;
236
+ left: 0;
237
+ width: 100%;
238
+ height: 100%;
239
+ z-index: 1;
240
+ display: flex;
241
+ justify-content: center;
242
+ align-items: flex-end;
243
+ }
244
+ .p_toolRightToRight .rightMoreButton div{
245
+ width:calc(100% - 50px);
246
+ padding: 16px 16px 10px 20px;
247
+ font-weight: 500;
248
+ color: #ffffff;
249
+ line-height: 17px;
250
+ font-size: 12px;
251
+ cursor:pointer;
252
+ }
253
+
254
+ .p_newDialog {
255
+ width: 252px;
256
+ height: 40px;
257
+ min-height:40px;
258
+ background: linear-gradient( 45deg, #1551FF 0%, #8F4BFF 100%);
259
+ margin-top: 20px;
260
+ border-radius: 20px;
261
+ cursor: pointer;
262
+ display: flex;
263
+ align-items: center;
264
+ justify-content: center;
265
+ }
266
+
267
+ .p_newDialog img {
268
+ width: 18px;
269
+ }
270
+
271
+ .p_newDialog .p_newDialogText {
272
+ color: #fff;
273
+ margin-left: 6px;
274
+ }
275
+ `
276
+
277
+ const defaultList = [
278
+ {
279
+ backgroundImg: 'https://trans-from-yuntu-resourse.oss-cn-beijing.aliyuncs.com/smartSchool/appCreator/ai/drop-down-item-card-01.png',
280
+ title: '我这学期的课程安排是什么样?',
281
+ },
282
+ {
283
+ backgroundImg: 'https://trans-from-yuntu-resourse.oss-cn-beijing.aliyuncs.com/smartSchool/appCreator/ai/drop-down-item-card-02.png',
284
+ title: '我上个学期的成绩是多少?',
285
+ },
286
+ {
287
+ backgroundImg: 'https://trans-from-yuntu-resourse.oss-cn-beijing.aliyuncs.com/smartSchool/appCreator/ai/drop-down-item-card-03.png',
288
+ title: '哪里可以找到心理咨询服务?',
289
+ },
290
+ ];
291
+
292
+ const formatFileSize = (bytes) => {
293
+ // 如果字节数为0,直接返回
294
+ if(isEmpty(bytes)) {
295
+ return { formattedSize: 0, unit: 'B' };
296
+ }
297
+ if(bytes === 0) return { formattedSize: 0, unit: 'B' };
298
+
299
+ // 定义单位和对应的字节数(1024进制)
300
+ const units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
301
+ // 计算合适的单位索引
302
+ const index = Math.floor(Math.log(bytes) / Math.log(1024));
303
+ // 将字节数转换为目标单位
304
+ const size = bytes / Math.pow(1024, index);
305
+ // 保留两位小数,并去除多余的0
306
+ const formattedSize = size.toFixed(2).replace(/\.?0+$/, '');
307
+ return { formattedSize, unit: units[index] }
308
+ }
309
+
310
+
311
+ const api_key = 'sk-mniUFDpcWwvNF3iFzssXa6etN-S_Y4AApyHYcBU44L0';
312
+
313
+
314
+ export class ToolDialog extends React.Component {
315
+ state = {
316
+ historyList: [], // 历史对话列表
317
+ sessionId: uuidv4(), // 当前激活的对话对应的sessionId
318
+ dropDownList: [],
319
+ sceneInfo: {},
320
+ currentFlow: {},
321
+ };
322
+
323
+ async componentDidMount() {
324
+ if(isEmpty(this.props.sceneId)){
325
+ // 兼容非场景打开的情况
326
+ this.getHistoryList({},true);
327
+ }else{
328
+ const sceneData = await this.getSceneInfo();
329
+ if(isEmpty(sceneData)) {
330
+ this.getHistoryList({},true);
331
+ } else {
332
+ this.getHistoryList(sceneData,true);
333
+ }
334
+ }
335
+ }
336
+
337
+ getCurrentFlowHistory=(flowId)=>{
338
+ let { userInfo = {} } = this.props;
339
+ const { sessionId } = this.state;
340
+ if(isEmpty(userInfo.code)) {
341
+ userInfo.code = sessionId;
342
+ }
343
+ const operationId = userInfo['code'] || '';
344
+ getHistoryList(this.props.hostUrl, flowId, operationId).then((res) => {
345
+ if(res.status === 200){
346
+ this.setState({ historyList: res.data });
347
+ }
348
+ });
349
+ }
350
+
351
+ // 获取历史对话列表
352
+ getHistoryList = (sceneData, isRefreshWords) => {
353
+ const { sceneId, appId: flowId, isShowSideLeft } = this.props;
354
+ if(isEmpty(sceneId)){
355
+ // 单独组件情况
356
+ if(isRefreshWords){
357
+ this.getFlowInfo().then(currentFlow=>{
358
+ const dropDownList = this.getDropDownList(currentFlow?.welcome_words||[]);
359
+ this.setState({ dropDownList, currentFlow })
360
+ })
361
+ }
362
+ if(isShowSideLeft) {
363
+ this.getCurrentFlowHistory(flowId)
364
+ }
365
+ }else{
366
+ const currentScene = sceneData||this.state.sceneInfo;
367
+ const currentFlow = currentScene.flows[0];
368
+ const dropDownList = this.getDropDownList(currentFlow?.welcome_words||[]);
369
+ if(!isEmpty(sceneData)){
370
+ this.setState({ currentFlow, dropDownList })
371
+ }else if(isEmpty(this.state.sceneInfo)){
372
+ this.setState({ dropDownList:defaultList })
373
+ }
374
+ if(isShowSideLeft) {
375
+ this.getCurrentFlowHistory(currentFlow.id)
376
+ }
377
+ }
378
+ };
379
+
380
+ getSceneInfo = async ()=>{
381
+ const res = await getSceneInfo(this.props.hostUrl, this.props.sceneId, api_key);
382
+ if(res.status === 200){
383
+ this.setState({ sceneInfo: res.data });
384
+ }
385
+ return res.data;
386
+ }
387
+
388
+ getFlowInfo = async () => {
389
+ const res = await getFlowInfo(this.props.hostUrl, this.props.appId, api_key);
390
+ if(res.status === 200) {
391
+ this.setState({ sceneInfo: res.data });
392
+ }
393
+ return res.data;
394
+ }
395
+
396
+ // 新建对话
397
+ newDialog = () => {
398
+ if(this.state.dropDownList) {
399
+ messageTip.info("当前已是最新对话")
400
+ return;
401
+ }
402
+ this.setState({ sessionId: uuidv4() });
403
+ this.setState({ dropDownList: this.getDropDownList(this.state.currentFlow?.welcome_words||[]) })
404
+ }
405
+
406
+ updateSessionId = (sessionId) => {
407
+ this.setState({ sessionId });
408
+ };
409
+
410
+ getDropDownList = (welcome_words)=>{
411
+ if(isEmpty(welcome_words)){
412
+ return defaultList;
413
+ }
414
+ return welcome_words.slice(0,3).map((question,index)=>(
415
+ {
416
+ backgroundImg:defaultList[index].backgroundImg,
417
+ title:question,
418
+ }
419
+ ))
420
+ }
421
+
422
+ render() {
423
+ const {
424
+ title,
425
+ appId: flowId,
426
+ hostUrl,
427
+ setDialogVisible,
428
+ userInfo,
429
+ boxStyle,
430
+ isShowSideRight,
431
+ isShowSideLeft = true,
432
+ tags = [],
433
+ agentUrl = aiAvatarPng,
434
+ agentName = '校园智多星',
435
+ logoWidth = '42px',
436
+ logoFontSize = '26px',
437
+ isTitleSideIcon = false,// 是否将左侧历史顶部icon移到中间顶部左侧蓝点位置
438
+ modalIndex,
439
+ isShowUploadButton,
440
+ dropManUrl,
441
+ modalWidth
442
+ } = this.props;
443
+ const { sceneInfo, currentFlow = {} } = this.state;
444
+ const { flows = [], name: sceneName, character } = sceneInfo;
445
+ return (
446
+ <div style={boxStyle}>
447
+ <style dangerouslySetInnerHTML={{ __html: style }}></style>
448
+ <div style={{ position: 'absolute', top: '18px', right: '18px', zIndex: modalIndex }}>
449
+ {isFunction(setDialogVisible) &&
450
+ <img onClick={() => setDialogVisible(false)} className="p_closeImg" src={closePng}/>}
451
+ </div>
452
+ <div className="p_toolDialog">
453
+ {
454
+ isShowSideLeft && <div className="p_toolLeft">
455
+ <div className="p_toolLogo">
456
+ <img className="p_logoImg" style={{ width: logoWidth, borderRadius: 15 }} src={agentUrl}/>
457
+ <div className="p_logoText" style={{ fontSize: logoFontSize }}>{agentName}</div>
458
+ </div>
459
+ <div className="p_historyDialog">
460
+ <div className="p_historyTitle">
461
+ <img className="p_historyImg" src={historyPng}/>
462
+ <div className="p_dialogTitle">对话列表</div>
463
+ </div>
464
+ {this.state.historyList.length > 0 ? (
465
+ <div className="p_historyList">
466
+ {this.state.historyList?.map((item) => (
467
+ <div
468
+ key={item.session_id}
469
+ className="p_historyItem"
470
+ onClick={() => {
471
+ this.setState({ dropDownList: undefined })
472
+ this.updateSessionId(item.session_id);
473
+ }}
474
+ >
475
+ <div
476
+ className={`p_historyName ${
477
+ item.session_id === this.state.sessionId ? 'p_activeHistoryName' : ''
478
+ }`}
479
+ >
480
+ {item.text}
481
+ </div>
482
+ </div>
483
+ ))}
484
+ </div>
485
+ ) : (
486
+ <div className="p_historyListEmpty">
487
+ <img src={historyListEmptyPng}/>
488
+ <div className="p_historyListEmptyText">暂无对话记录</div>
489
+ </div>
490
+ )}
491
+ </div>
492
+ <div className="p_newDialog" onClick={() => {
493
+ this.newDialog()
494
+ }}>
495
+ <img src={addPng}/>
496
+ <div className="p_newDialogText">新建对话</div>
497
+ </div>
498
+ </div>
499
+ }
500
+ <div className="p_toolRight">
501
+ <ChatWidget
502
+ window_title={currentFlow?.name || title}
503
+ flow_id={currentFlow?.id || flowId}
504
+ tags={currentFlow?.keywords || tags}
505
+ host_url={hostUrl}
506
+ api_key={api_key}
507
+ session_id={this.state.sessionId}
508
+ userInfo={userInfo}
509
+ getHistoryList={this.getHistoryList}
510
+ setDropDownList={(list) => this.setState({ dropDownList: list })}
511
+ dropDownList={this.state.dropDownList}
512
+ baseConfig={{ isTitleSideIcon, logoWidth, agentUrl }}
513
+ isShowUploadButton={isShowUploadButton}
514
+ dropManUrl={character || dropManUrl}
515
+ modalWidth={modalWidth}
516
+ />
517
+ </div>
518
+ {
519
+ isShowSideRight &&
520
+ <div className={"p_toolRightToRight"}>
521
+ <div className={"rightInnerContainer"}>
522
+ <div>
523
+ <h3 className={"rightSideTitle"}>
524
+ <img width={15} src={self_skills}/>
525
+ <span style={{ color: "#333333" }}>专项技能</span>
526
+ </h3>
527
+ {
528
+ isEmpty(flows) ?
529
+ <Skeleton
530
+ title={false}
531
+ active
532
+ paragraph={{ rows: 5, width: '100%' }}
533
+ />
534
+ :
535
+ <div className={"rightSkillContainer"}>
536
+ <div className={"rightSkillList"}>
537
+ {flows.slice(0, 12).map((item) => (
538
+ <div className={"rightSkillItem"} key={item.id} onClick={() => {
539
+ // 右侧点击一个技能,更新sessionId,切换当前flow信息,重新查询历史记录
540
+ this.setState({
541
+ sessionId: uuidv4(),
542
+ currentFlow: item,
543
+ dropDownList: this.getDropDownList(item?.welcome_words||[])
544
+ });
545
+ this.getCurrentFlowHistory(item.id);
546
+ }}>
547
+ <img
548
+ src={item.icon}
549
+ alt={item.name}/>
550
+ <p>{item.name}</p>
551
+ </div>
552
+ ))}
553
+ </div>
554
+ </div>
555
+ }
556
+ </div>
557
+ <div>
558
+ <h3 className={"rightKnowledgeTitle"}>
559
+ <img width={15} src={self_knowledge}/>
560
+ <span style={{ color: "#333333" }}>个人知识库</span>
561
+ </h3>
562
+ {
563
+ isEmpty(currentFlow) ?
564
+ <Skeleton
565
+ title={false}
566
+ active
567
+ paragraph={{ rows: 5, width: '100%' }}
568
+ /> :
569
+ <div className={"rightKnowledgeContainer"}>
570
+ <img src={moreBg}/>
571
+ <div style={{ position: 'absolute', top: '40px', left: '16px' }}>
572
+ <div>文件总数<span style={{
573
+ padding: 8,
574
+ fontSize: '20px',
575
+ fontWeight: 700
576
+ }}>{currentFlow.k_count || 0}</span>个
577
+ </div>
578
+ <div style={{ marginTop: 10 }}>文件总量<span style={{
579
+ padding: 8,
580
+ fontSize: '20px',
581
+ fontWeight: 700
582
+ }}>{formatFileSize(currentFlow.k_size).formattedSize}</span>{formatFileSize(currentFlow.k_size).unit}
583
+ </div>
584
+ </div>
585
+ <div className={"rightMoreButton"}>
586
+ <div className={"rightMoreTitle"} onClick={() => messageTip.info("敬请期待")}>训练你的专属知识库</div>
587
+ </div>
588
+ </div>
589
+ }
590
+ </div>
591
+ </div>
592
+ </div>
593
+ }
594
+ </div>
595
+ </div>
596
+ );
597
+ }
598
+ }
599
+
600
+ export default ToolDialog;