yt-chat-components 2.0.6 → 2.0.7

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.
@@ -0,0 +1,389 @@
1
+ import { Avatar, Button, Input, Layout, List, Modal, Tooltip, Typography, Dropdown } from 'antd';
2
+ import {
3
+ AlertOutlined,
4
+ BellOutlined,
5
+ FolderOutlined, LeftOutlined,
6
+ MessageOutlined,
7
+ PlusOutlined,
8
+ QuestionCircleOutlined, RightOutlined,
9
+ SearchOutlined,
10
+ TeamOutlined,
11
+ UserOutlined,
12
+ } from '@ant-design/icons';
13
+ import { useEffect, useState } from "react";
14
+ import { isEmpty, isFunction } from "lodash";
15
+ const { Sider } = Layout;
16
+ const { Text } = Typography;
17
+ const { confirm } = Modal;
18
+
19
+ const displayStyle = { display: 'none' }
20
+
21
+ const LeftMenu = ({
22
+ onNewChat,
23
+ onSelectSession,
24
+ activeId,
25
+ appId,
26
+ flow,
27
+ handleLoadHistoryList,
28
+ userInfo,
29
+ sceneInfo = {},
30
+ allFlowList = [],
31
+ addToScene,
32
+ removeFromScene
33
+ }) => {
34
+ const [collapsed, setCollapsed] = useState(false);
35
+ const [historyList, setHistoryList] = useState([]);
36
+ const [appList, setAppList] = useState([]);
37
+ const [filter, setFilter] = useState('');
38
+ const [isShowSearch, setIsShowSearch] = useState(false);
39
+ const [isShowAllFlowList, setIsShowAllFlowList] = useState(false);
40
+ useEffect(() => {
41
+ }, [appId])
42
+
43
+ const handleDelete = (item) => {
44
+ confirm({
45
+ centered: true,
46
+ title: '确认删除该流程?',
47
+ content: `删除后仍可以添加到该场景,是否删除?`,
48
+ okText: '删除',
49
+ okType: 'danger',
50
+ cancelText: '取消',
51
+ onOk: () => {
52
+ removeFromScene && removeFromScene(item);
53
+ },
54
+ });
55
+ };
56
+
57
+ return (
58
+ <>
59
+ <Sider
60
+ width={300}
61
+ collapsible={true}
62
+ defaultCollapsed={false}
63
+ collapsed={collapsed}
64
+ collapsedWidth={0}
65
+ trigger={<Button
66
+ icon={collapsed ? <RightOutlined/> : <LeftOutlined/>}
67
+ style={{ borderRadius: '20px', position: 'absolute', top: '100px', right: '25px' }}
68
+ onClick={() => setCollapsed(!collapsed)}
69
+ />}
70
+ zeroWidthTriggerStyle={{ backgroundColor: 'transparent' }}
71
+ >
72
+ <div style={{
73
+ display: 'flex',
74
+ flexDirection: 'row',
75
+ position: 'relative',
76
+ }}
77
+ >
78
+ {
79
+ !collapsed && <div style={{
80
+ width: '64px',
81
+ display: 'flex',
82
+ alignItems: 'center',
83
+ flexDirection: 'column',
84
+ backgroundColor: '#FFFFFF',
85
+ borderRight: '1px solid #E5E5E5'
86
+ }}>
87
+ <div style={{ marginTop: '16px', marginBottom: '64px' }}>
88
+ <Avatar size={32}
89
+ style={{
90
+ background: '#ff4d4f',
91
+ fontSize: '20px',
92
+ width: '40px',
93
+ height: '40px',
94
+ borderRadius: '6px',
95
+ cursor: 'pointer'
96
+ }}>
97
+ {userInfo?.name.substring(0, 1) || '我'}
98
+ </Avatar>
99
+ </div>
100
+ <div style={{ display: 'flex', flexDirection: 'column', flex: 1, alignItems: 'center', gap: 12 }}>
101
+ <MessageOutlined title={'聊天'} style={{
102
+ color: '#000000',
103
+ fontSize: '20px',
104
+ padding: '12px', ...displayStyle
105
+ }}/>
106
+ <FolderOutlined title={'资源'} style={{
107
+ color: '#000000',
108
+ fontSize: '20px',
109
+ padding: '12px', ...displayStyle
110
+ }}/>
111
+ <TeamOutlined title={'团队'}
112
+ style={{ color: '#000000', fontSize: '20px', padding: '12px', ...displayStyle }}/>
113
+ <AlertOutlined title={'专家'} style={{
114
+ color: '#000000',
115
+ fontSize: '20px',
116
+ padding: '12px', ...displayStyle
117
+ }}/>
118
+ </div>
119
+ <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 12 }}>
120
+ <SearchOutlined title={'搜索'} style={{
121
+ color: '#000000',
122
+ fontSize: '20px',
123
+ padding: '12px', ...displayStyle
124
+ }}/>
125
+ <QuestionCircleOutlined title={'帮助'} style={{
126
+ color: '#000000',
127
+ fontSize: '20px',
128
+ padding: '12px', ...displayStyle
129
+ }}/>
130
+ <BellOutlined title={'通知'}
131
+ style={{ color: '#000000', fontSize: '20px', padding: '12px', ...displayStyle }}/>
132
+ </div>
133
+ <div style={{ margin: '16px 0' }}>
134
+ {/*<Avatar size={32}*/}
135
+ {/* style={{*/}
136
+ {/* background: '#ff4d4f',*/}
137
+ {/* fontSize: '20px',*/}
138
+ {/* width: '40px',*/}
139
+ {/* height: '40px',*/}
140
+ {/* }}>*/}
141
+ {/* 你*/}
142
+ {/*</Avatar>*/}
143
+ </div>
144
+ </div>
145
+ }
146
+ {
147
+ !collapsed && <div style={{
148
+ width: '266px',
149
+ height: '100vh',
150
+ background: '#fff',
151
+ borderRight: '1px solid #E5E5E5',
152
+ display: 'flex',
153
+ flexDirection: 'column',
154
+ }}>
155
+ <div
156
+ style={{
157
+ padding: '22px 16px 14px',
158
+ borderBottom: '#E5E5E5 solid 1px',
159
+ display: 'flex',
160
+ alignItems: 'center',
161
+ justifyContent: 'space-between',
162
+ }}
163
+ >
164
+ <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
165
+ <div style={{ display: 'flex', flexDirection: 'column' }}>
166
+ <Text strong>聊天</Text>
167
+ {/*<Text type="secondary" style={{ fontSize: 12 }}>*/}
168
+ {/* {flow.name}*/}
169
+ {/*</Text>*/}
170
+ </div>
171
+ </div>
172
+ <Button
173
+ type="primary"
174
+ style={{display: 'flex', alignItems: 'center'}}
175
+ shape="circle"
176
+ icon={<PlusOutlined style={{
177
+ fontSize: 20,
178
+ width: 27,
179
+ height: 27,
180
+ display: 'flex',
181
+ justifyContent: 'center'
182
+ }}/>}
183
+ size="small"
184
+ title={'添加助手'}
185
+ onClick={() => setIsShowAllFlowList(true)}
186
+ />
187
+ </div>
188
+
189
+ {/* 会话 / 菜单列表 */}
190
+ <div
191
+ style={{
192
+ flex: 1,
193
+ overflowY: 'auto',
194
+ padding: '0 8px 8px',
195
+ }}
196
+ >
197
+ <div style={{ padding: '8px 8px 8px' }}>
198
+ <Input
199
+ placeholder="搜索智能体"
200
+ prefix={<SearchOutlined/>}
201
+ allowClear
202
+ size="small"
203
+ onChange={(e) => setFilter(e.target.value)}
204
+ />
205
+ </div>
206
+ <div style={{ marginBottom: 16 }}>
207
+ <List
208
+ size="small"
209
+ dataSource={sceneInfo.flows?.filter(item => item.name.indexOf(filter) > -1)}
210
+ renderItem={item => {
211
+ const isActive = activeId === item.id;
212
+
213
+ return (
214
+ <Dropdown
215
+ trigger={['contextMenu']}
216
+ menu={{
217
+ items: [
218
+ {
219
+ key: 'delete',
220
+ label: '删除',
221
+ danger: true,
222
+ onClick: () => handleDelete(item),
223
+ },
224
+ ],
225
+ }}
226
+ >
227
+ <List.Item
228
+ style={{
229
+ padding: '8px 8px',
230
+ borderRadius: 8,
231
+ margin: '2px 0',
232
+ cursor: 'pointer',
233
+ background: isActive ? 'rgba(84,52,255,0.06)' : 'transparent',
234
+ }}
235
+ onClick={() => onSelectSession && onSelectSession(item)}
236
+ >
237
+ <List.Item.Meta
238
+ style={{ display: 'flex', alignItems: 'center' }}
239
+ avatar={
240
+ <img
241
+ src={item.icon}
242
+ style={{ width: 28, height: 28, borderRadius: 4 }}
243
+ />
244
+ }
245
+ title={
246
+ <div
247
+ style={{
248
+ display: 'flex',
249
+ justifyContent: 'space-between',
250
+ alignItems: 'center',
251
+ }}
252
+ >
253
+ <span
254
+ style={{
255
+ fontWeight: isActive ? 600 : 400,
256
+ }}
257
+ >
258
+ {item.name}
259
+ </span>
260
+ </div>
261
+ }
262
+ description={
263
+ item.content ? (
264
+ <Tooltip title={item.content} placement={'bottomRight'}>
265
+ <Text
266
+ type="secondary"
267
+ style={{ fontSize: 12 }}
268
+ ellipsis
269
+ >
270
+ {item.content}
271
+ </Text>
272
+ </Tooltip>
273
+ ) : null
274
+ }
275
+ />
276
+ </List.Item>
277
+ </Dropdown>
278
+ );
279
+ }}
280
+ />
281
+ </div>
282
+ </div>
283
+
284
+ {/* 底部用户/设置区 */}
285
+ <div
286
+ style={{
287
+ borderTop: '1px solid #E5E5E5',
288
+ padding: '8px 12px',
289
+ display: 'none',
290
+ alignItems: 'center',
291
+ justifyContent: 'space-between',
292
+ }}
293
+ >
294
+ <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
295
+ <Avatar size={28} icon={<UserOutlined/>}/>
296
+ <div style={{ display: 'flex', flexDirection: 'column' }}>
297
+ <Text style={{ fontSize: 13 }}>招生咨询老师</Text>
298
+ <Text type="secondary" style={{ fontSize: 11 }}>
299
+ 在线
300
+ </Text>
301
+ </div>
302
+ </div>
303
+ <Button size="small" type="link" style={{ padding: 0 }}>
304
+ 设置
305
+ </Button>
306
+ </div>
307
+ </div>
308
+ }
309
+ </div>
310
+ </Sider>
311
+ <Modal
312
+ title={null}
313
+ open={isShowAllFlowList}
314
+ onCancel={() => setIsShowAllFlowList(false)}
315
+ footer={null}
316
+ width={1200}
317
+ centered={true}
318
+ // style={{ top: 0, height: '100%' }}
319
+ >
320
+ <List
321
+ size="large"
322
+ dataSource={allFlowList.filter(flow => sceneInfo.flow_ids.indexOf(flow.id) === -1)}
323
+ renderItem={item => {
324
+ const isActive = activeId === item.id;
325
+ return (
326
+ <List.Item
327
+ style={{
328
+ padding: '8px 8px',
329
+ borderRadius: 8,
330
+ margin: '2px 0',
331
+ cursor: 'pointer',
332
+ background: isActive ? 'rgba(84,52,255,0.06)' : 'transparent',
333
+ }}
334
+ actions={[
335
+ <a
336
+ size="small"
337
+ style={{ padding: 0,width: 80 }}
338
+ onClick={() => {
339
+ if(isFunction(addToScene)){
340
+ addToScene(item)
341
+ }
342
+ }}
343
+ >添加</a>
344
+ ]}
345
+ >
346
+ <List.Item.Meta
347
+ style={{ display: 'flex', alignItems: 'center' }}
348
+ avatar={
349
+ <img
350
+ src={item.icon}
351
+ style={{ width: 28, height: 28, borderRadius: 4, }}/>
352
+ }
353
+ title={
354
+ <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', }}>
355
+ <span
356
+ style={{
357
+ fontWeight: isActive ? 600 : 400,
358
+ }}
359
+ >
360
+ {item.name}
361
+ </span>
362
+ </div>
363
+ }
364
+ description={
365
+ item.content ? (
366
+ <Tooltip title={item.content} placement={'bottomRight'}>
367
+ <Text
368
+ type="secondary"
369
+ style={{ fontSize: 12 }}
370
+ ellipsis
371
+ >
372
+ {item.content}
373
+ </Text>
374
+ </Tooltip>
375
+ ) : null
376
+ }
377
+ />
378
+ </List.Item>
379
+ );
380
+ }}
381
+ >
382
+ </List>
383
+ </Modal>
384
+ </>
385
+ )
386
+ ;
387
+ }
388
+
389
+ export default LeftMenu;