bi-sdk-react 0.0.4 → 0.0.5
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/dist/es/css/bi-sdk.css +1 -1
- package/dist/es/js/bi-sdk.es.js +270 -63
- package/dist/types/components/PageDesigner.d.ts +9 -1
- package/dist/types/components/context/DesignerContext.d.ts +5 -2
- package/dist/types/components/context/EnvContext.d.ts +2 -1
- package/dist/types/components/icon/IconFont.d.ts +2 -1
- package/dist/types/components/layout/PageCanvas.d.ts +2 -0
- package/dist/types/components/panel/AiPanel.d.ts +4 -0
- package/dist/types/components/panel/ChatInput.d.ts +13 -6
- package/dist/types/components/panel/DatasetPanel.d.ts +11 -0
- package/dist/types/components/panel/PaneHeader.d.ts +1 -0
- package/dist/types/components/panel/PropertiesPanel.d.ts +3 -1
- package/dist/types/components/plugins/@antd/item-props/EchartsProps.d.ts +2 -2
- package/dist/types/components/plugins/@antd/item-props/TextProps.d.ts +1 -0
- package/dist/types/components/plugins/@antd/items/TableRender.d.ts +1 -0
- package/dist/types/components/plugins/@antd/items/TextRender.d.ts +1 -0
- package/dist/types/components/typing.d.ts +97 -2
- package/dist/types/components/utils.d.ts +1 -0
- package/dist/umd/css/bi-sdk.css +1 -1
- package/dist/umd/js/bi-sdk.umd.min.js +274 -67
- package/package.json +1 -1
- package/src/components/PageDesigner.tsx +229 -36
- package/src/components/context/DesignerContext.tsx +15 -3
- package/src/components/context/EnvContext.tsx +4 -1
- package/src/components/icon/IconFont.tsx +15 -11
- package/src/components/layout/PageCanvas.tsx +4 -2
- package/src/components/layout/PageItem.tsx +1 -1
- package/src/components/panel/AiPanel.tsx +609 -43
- package/src/components/panel/ChatInput.tsx +259 -147
- package/src/components/panel/DatasetPanel.tsx +65 -0
- package/src/components/panel/PaneHeader.tsx +3 -2
- package/src/components/panel/PropertiesPanel.tsx +332 -125
- package/src/components/plugins/@antd/index.ts +12 -8
- package/src/components/plugins/@antd/item-props/EchartsProps.tsx +52 -22
- package/src/components/plugins/@antd/item-props/HtmlProps.tsx +8 -9
- package/src/components/plugins/@antd/item-props/TextProps.tsx +13 -1
- package/src/components/plugins/@antd/items/EchartsRender.tsx +9 -1
- package/src/components/plugins/@antd/items/HtmlRender.tsx +13 -1
- package/src/components/plugins/@antd/items/ListRender.tsx +18 -1
- package/src/components/plugins/@antd/items/TableRender.tsx +16 -1
- package/src/components/plugins/@antd/items/TextRender.tsx +3 -1
- package/src/components/styles.css +20 -0
- package/src/components/typing.ts +111 -2
- package/src/components/utils.ts +40 -0
- package/src/example.tsx +314 -13
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
SendOutlined,
|
|
2
|
+
AudioOutlined,
|
|
3
|
+
DeleteOutlined as DelIcon, DeleteOutlined, FileExcelOutlined, InboxOutlined, SendOutlined
|
|
5
4
|
} from "@ant-design/icons";
|
|
6
5
|
import {
|
|
7
6
|
Button,
|
|
8
7
|
Dropdown,
|
|
9
8
|
Input,
|
|
10
|
-
|
|
9
|
+
Modal,
|
|
11
10
|
Tooltip,
|
|
12
11
|
Typography,
|
|
13
12
|
Upload,
|
|
13
|
+
message
|
|
14
14
|
} from "antd";
|
|
15
15
|
import React, {
|
|
16
16
|
useEffect,
|
|
@@ -20,8 +20,8 @@ import React, {
|
|
|
20
20
|
useState,
|
|
21
21
|
} from "react";
|
|
22
22
|
import styled from "styled-components";
|
|
23
|
-
import * as XLSX from "xlsx";
|
|
24
23
|
import { IconFont } from "../icon/IconFont";
|
|
24
|
+
import { FetchType } from "../typing";
|
|
25
25
|
|
|
26
26
|
export type ChatInputProps = {
|
|
27
27
|
value?: string;
|
|
@@ -30,22 +30,25 @@ export type ChatInputProps = {
|
|
|
30
30
|
sending?: boolean;
|
|
31
31
|
rows?: number;
|
|
32
32
|
agentList?: { id: string | number; name: string }[];
|
|
33
|
-
title?: string;
|
|
34
33
|
agentId?: string | number | null;
|
|
35
34
|
attachments?: any[];
|
|
36
35
|
onInput?: (text: string) => void;
|
|
37
36
|
onSubmit?: (data: {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
csvData: Record<string, string>;
|
|
37
|
+
message: string;
|
|
38
|
+
agents?: { id: string | number; name: string }[] | null;
|
|
39
|
+
files?: { id: string; name: string; extension: string }[] | null;
|
|
42
40
|
}) => void;
|
|
43
|
-
onUpdateTitle?: (title: string) => void;
|
|
44
41
|
onUpdateAgentId?: (id: string | number | null) => void;
|
|
45
42
|
onUpdateAttachments?: (list: any[]) => void;
|
|
43
|
+
onUploading?: FetchType["upload"];
|
|
44
|
+
style?: React.CSSProperties;
|
|
46
45
|
};
|
|
47
46
|
|
|
48
|
-
const
|
|
47
|
+
const AgentListDropdownContent = styled.div`
|
|
48
|
+
max-height: 400px;
|
|
49
|
+
overflow: auto;
|
|
50
|
+
background: #fff;
|
|
51
|
+
|
|
49
52
|
ul.agent-list {
|
|
50
53
|
margin: 0;
|
|
51
54
|
padding: 0;
|
|
@@ -70,6 +73,9 @@ const Wrapper = styled.div`
|
|
|
70
73
|
text-overflow: ellipsis;
|
|
71
74
|
white-space: nowrap;
|
|
72
75
|
}
|
|
76
|
+
`;
|
|
77
|
+
|
|
78
|
+
const Wrapper = styled.div`
|
|
73
79
|
.chat-input {
|
|
74
80
|
display: flex;
|
|
75
81
|
flex-direction: column;
|
|
@@ -241,21 +247,6 @@ const Wrapper = styled.div`
|
|
|
241
247
|
.agent-trigger:hover {
|
|
242
248
|
background-color: #f7f7f7;
|
|
243
249
|
}
|
|
244
|
-
.title-toggle {
|
|
245
|
-
display: none;
|
|
246
|
-
align-items: center;
|
|
247
|
-
gap: 6px;
|
|
248
|
-
background-color: #ffffff;
|
|
249
|
-
border: solid 1px #dcdcdc;
|
|
250
|
-
border-radius: 5px;
|
|
251
|
-
padding: 0 4px;
|
|
252
|
-
height: 26px;
|
|
253
|
-
}
|
|
254
|
-
.title-toggle .label {
|
|
255
|
-
color: #666;
|
|
256
|
-
font-size: 12px;
|
|
257
|
-
user-select: none;
|
|
258
|
-
}
|
|
259
250
|
.attach-upload {
|
|
260
251
|
display: inline-flex;
|
|
261
252
|
align-items: center;
|
|
@@ -269,6 +260,9 @@ const Wrapper = styled.div`
|
|
|
269
260
|
font-size: 12px;
|
|
270
261
|
cursor: pointer;
|
|
271
262
|
}
|
|
263
|
+
.ant-btn .anticon {
|
|
264
|
+
color: var(--ant-color-text-label);
|
|
265
|
+
}
|
|
272
266
|
.tips {
|
|
273
267
|
color: #999;
|
|
274
268
|
font-size: 12px;
|
|
@@ -298,6 +292,154 @@ const Wrapper = styled.div`
|
|
|
298
292
|
const DEFAULT_AGENT_LIST: any[] = [];
|
|
299
293
|
const DEFAULT_ATTACHMENTS: any[] = [];
|
|
300
294
|
|
|
295
|
+
const ALLOWED_MIME_TYPES = [
|
|
296
|
+
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
297
|
+
"audio/wav",
|
|
298
|
+
];
|
|
299
|
+
|
|
300
|
+
const ALLOWED_EXTENSIONS = [".xlsx", ".wav"];
|
|
301
|
+
|
|
302
|
+
const FileUploadModal: React.FC<{
|
|
303
|
+
open: boolean;
|
|
304
|
+
onCancel: () => void;
|
|
305
|
+
onOk: (files: File[]) => void;
|
|
306
|
+
allowedExtensions: string[];
|
|
307
|
+
allowedMimeTypes: string[];
|
|
308
|
+
}> = ({ open, onCancel, onOk, allowedExtensions, allowedMimeTypes }) => {
|
|
309
|
+
const [fileList, setFileList] = useState<File[]>([]);
|
|
310
|
+
|
|
311
|
+
useEffect(() => {
|
|
312
|
+
if (open) {
|
|
313
|
+
setFileList([]);
|
|
314
|
+
}
|
|
315
|
+
}, [open]);
|
|
316
|
+
|
|
317
|
+
const handleOk = () => {
|
|
318
|
+
onOk(fileList);
|
|
319
|
+
onCancel();
|
|
320
|
+
};
|
|
321
|
+
const acceptFiles = [...ALLOWED_EXTENSIONS, ...ALLOWED_MIME_TYPES].join(",");
|
|
322
|
+
|
|
323
|
+
const props = {
|
|
324
|
+
name: "file",
|
|
325
|
+
multiple: true,
|
|
326
|
+
accept: acceptFiles,
|
|
327
|
+
fileList: [], // Managed manually
|
|
328
|
+
beforeUpload: (file: File) => {
|
|
329
|
+
const mimeOk = allowedMimeTypes.includes(file.type) || !file.type;
|
|
330
|
+
const ext = (file.name || "")
|
|
331
|
+
.substring(file.name.lastIndexOf("."))
|
|
332
|
+
.toLowerCase();
|
|
333
|
+
const extOk = allowedExtensions.includes(ext);
|
|
334
|
+
|
|
335
|
+
if (!mimeOk && !extOk) {
|
|
336
|
+
message.error(`不支持的文件类型: ${file.name}`);
|
|
337
|
+
return Upload.LIST_IGNORE;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
setFileList((prev) => [...prev, file]);
|
|
341
|
+
return false;
|
|
342
|
+
},
|
|
343
|
+
};
|
|
344
|
+
|
|
345
|
+
const removeFile = (index: number) => {
|
|
346
|
+
setFileList((prev) => prev.filter((_, i) => i !== index));
|
|
347
|
+
};
|
|
348
|
+
|
|
349
|
+
return (
|
|
350
|
+
<Modal
|
|
351
|
+
title="上传文件"
|
|
352
|
+
open={open}
|
|
353
|
+
okText="上传"
|
|
354
|
+
cancelText="取消"
|
|
355
|
+
onOk={handleOk}
|
|
356
|
+
onCancel={onCancel}
|
|
357
|
+
width={600}
|
|
358
|
+
>
|
|
359
|
+
<div style={{ marginBottom: 16 }}>
|
|
360
|
+
<Typography.Text type="secondary">
|
|
361
|
+
支持的文件类型:{allowedExtensions.join(", ")}
|
|
362
|
+
<br />
|
|
363
|
+
单次支持上传多个文件,请确保文件内容合规。
|
|
364
|
+
<br />
|
|
365
|
+
Excel 暂不支持加密文件。
|
|
366
|
+
<br />
|
|
367
|
+
不支持 xls 电子表格,请自行转换为 xlsx 格式。
|
|
368
|
+
<br />
|
|
369
|
+
Excel 仅支持第一行为表头、第二行开始为数据,不支持合并单元格。
|
|
370
|
+
</Typography.Text>
|
|
371
|
+
</div>
|
|
372
|
+
<Upload.Dragger {...props}>
|
|
373
|
+
<p className="ant-upload-drag-icon">
|
|
374
|
+
<InboxOutlined />
|
|
375
|
+
</p>
|
|
376
|
+
<p className="ant-upload-text">点击或将文件拖拽到此处上传</p>
|
|
377
|
+
<p className="ant-upload-hint">
|
|
378
|
+
支持上传Excel表格数据或音频文件进行分析
|
|
379
|
+
</p>
|
|
380
|
+
</Upload.Dragger>
|
|
381
|
+
{fileList.length > 0 && (
|
|
382
|
+
<div style={{ marginTop: 16 }}>
|
|
383
|
+
<Typography.Title level={5} style={{ fontSize: 14, marginBottom: 8 }}>
|
|
384
|
+
已选文件 ({fileList.length})
|
|
385
|
+
</Typography.Title>
|
|
386
|
+
<div
|
|
387
|
+
style={{
|
|
388
|
+
display: "flex",
|
|
389
|
+
flexDirection: "column",
|
|
390
|
+
gap: 8,
|
|
391
|
+
maxHeight: 200,
|
|
392
|
+
overflowY: "auto",
|
|
393
|
+
}}
|
|
394
|
+
>
|
|
395
|
+
{fileList.map((file, index) => (
|
|
396
|
+
<div
|
|
397
|
+
key={`${file.name}-${index}`}
|
|
398
|
+
style={{
|
|
399
|
+
display: "flex",
|
|
400
|
+
alignItems: "center",
|
|
401
|
+
justifyContent: "space-between",
|
|
402
|
+
padding: "8px 12px",
|
|
403
|
+
background: "#f5f5f5",
|
|
404
|
+
borderRadius: 4,
|
|
405
|
+
}}
|
|
406
|
+
>
|
|
407
|
+
<div
|
|
408
|
+
style={{
|
|
409
|
+
display: "flex",
|
|
410
|
+
alignItems: "center",
|
|
411
|
+
gap: 8,
|
|
412
|
+
overflow: "hidden",
|
|
413
|
+
}}
|
|
414
|
+
>
|
|
415
|
+
{file.name.endsWith(".xlsx") ? (
|
|
416
|
+
<FileExcelOutlined style={{ color: "#52c41a" }} />
|
|
417
|
+
) : (
|
|
418
|
+
<AudioOutlined style={{ color: "#1890ff" }} />
|
|
419
|
+
)}
|
|
420
|
+
<Typography.Text ellipsis style={{ maxWidth: 300 }}>
|
|
421
|
+
{file.name}
|
|
422
|
+
</Typography.Text>
|
|
423
|
+
<Typography.Text type="secondary" style={{ fontSize: 12 }}>
|
|
424
|
+
({(file.size / 1024).toFixed(1)} KB)
|
|
425
|
+
</Typography.Text>
|
|
426
|
+
</div>
|
|
427
|
+
<Button
|
|
428
|
+
type="text"
|
|
429
|
+
size="small"
|
|
430
|
+
icon={<DelIcon />}
|
|
431
|
+
onClick={() => removeFile(index)}
|
|
432
|
+
danger
|
|
433
|
+
/>
|
|
434
|
+
</div>
|
|
435
|
+
))}
|
|
436
|
+
</div>
|
|
437
|
+
</div>
|
|
438
|
+
)}
|
|
439
|
+
</Modal>
|
|
440
|
+
);
|
|
441
|
+
};
|
|
442
|
+
|
|
301
443
|
export const ChatInput = React.forwardRef<
|
|
302
444
|
{ focus: () => void },
|
|
303
445
|
ChatInputProps
|
|
@@ -310,19 +452,18 @@ export const ChatInput = React.forwardRef<
|
|
|
310
452
|
sending = false,
|
|
311
453
|
rows = 6,
|
|
312
454
|
agentList = DEFAULT_AGENT_LIST,
|
|
313
|
-
title = "",
|
|
314
455
|
agentId = null,
|
|
315
456
|
attachments = DEFAULT_ATTACHMENTS,
|
|
316
457
|
onInput,
|
|
317
458
|
onSubmit,
|
|
318
|
-
onUpdateTitle,
|
|
319
459
|
onUpdateAgentId,
|
|
320
460
|
onUpdateAttachments,
|
|
461
|
+
onUploading,
|
|
462
|
+
style = {},
|
|
321
463
|
},
|
|
322
464
|
ref
|
|
323
465
|
) => {
|
|
324
466
|
const inputRef = useRef<any>(null);
|
|
325
|
-
const [localTitle, setLocalTitle] = useState(title || "");
|
|
326
467
|
const [selectedAgent, setSelectedAgent] = useState<
|
|
327
468
|
{
|
|
328
469
|
id: string | number;
|
|
@@ -332,12 +473,14 @@ export const ChatInput = React.forwardRef<
|
|
|
332
473
|
const [localValue, setLocalValue] = useState(value || "");
|
|
333
474
|
const [lastSubmitAt, setLastSubmitAt] = useState(0);
|
|
334
475
|
const minIntervalMs = 400;
|
|
335
|
-
const [
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
476
|
+
const [localAttachments, setLocalAttachments] = useState<
|
|
477
|
+
{
|
|
478
|
+
id: string;
|
|
479
|
+
name: string;
|
|
480
|
+
size: number;
|
|
481
|
+
}[]
|
|
482
|
+
>(Array.isArray(attachments) ? attachments : []);
|
|
483
|
+
const [uploadModalOpen, setUploadModalOpen] = useState<boolean>(false);
|
|
341
484
|
const isMobile = useMemo(() => false, []);
|
|
342
485
|
useImperativeHandle(ref, () => ({
|
|
343
486
|
focus() {
|
|
@@ -348,23 +491,14 @@ export const ChatInput = React.forwardRef<
|
|
|
348
491
|
useEffect(() => {
|
|
349
492
|
onInput && onInput(localValue);
|
|
350
493
|
}, [localValue]);
|
|
351
|
-
|
|
352
|
-
// useEffect(() => {
|
|
353
|
-
// setSelectedAgent(
|
|
354
|
-
// agentId ? agentList.find((s) => s.id === agentId) || [] : []
|
|
355
|
-
// );
|
|
356
|
-
// }, [agentId, agentList]);
|
|
494
|
+
|
|
357
495
|
useEffect(
|
|
358
496
|
() => setLocalAttachments(Array.isArray(attachments) ? attachments : []),
|
|
359
497
|
[attachments]
|
|
360
498
|
);
|
|
499
|
+
|
|
361
500
|
const canSubmit = !!(localValue && localValue.trim());
|
|
362
501
|
|
|
363
|
-
const onTitleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
364
|
-
const v = e.target.value;
|
|
365
|
-
setLocalTitle(v);
|
|
366
|
-
onUpdateTitle && onUpdateTitle(v);
|
|
367
|
-
};
|
|
368
502
|
const onAgentSelect = (item: { id: string | number; name: string }) => {
|
|
369
503
|
const id = item.id || null;
|
|
370
504
|
onUpdateAgentId && onUpdateAgentId(id);
|
|
@@ -383,52 +517,30 @@ export const ChatInput = React.forwardRef<
|
|
|
383
517
|
submit();
|
|
384
518
|
}
|
|
385
519
|
};
|
|
386
|
-
const
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
});
|
|
392
|
-
const result: Record<string, string> = {};
|
|
393
|
-
workbook.SheetNames.forEach((name) => {
|
|
394
|
-
const sheet = workbook.Sheets[name];
|
|
395
|
-
const csv = XLSX.utils.sheet_to_csv(sheet);
|
|
396
|
-
result[name] = csv;
|
|
397
|
-
});
|
|
398
|
-
return result;
|
|
399
|
-
};
|
|
400
|
-
const beforeUploadXlsx = (file: File) => {
|
|
401
|
-
const mimeOk =
|
|
402
|
-
file.type ===
|
|
403
|
-
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" ||
|
|
404
|
-
!file.type;
|
|
405
|
-
const extOk = (file.name || "").toLowerCase().endsWith(".xlsx");
|
|
406
|
-
if (!mimeOk || !extOk) {
|
|
407
|
-
return Upload.LIST_IGNORE;
|
|
408
|
-
}
|
|
409
|
-
const reader = new FileReader();
|
|
410
|
-
reader.onload = async (e) => {
|
|
520
|
+
const handleUploadFiles = async (files: File[]) => {
|
|
521
|
+
setUploadModalOpen(false);
|
|
522
|
+
if (!onUploading || !files.length) return;
|
|
523
|
+
const newAttachments: typeof localAttachments = [];
|
|
524
|
+
for (const file of files) {
|
|
411
525
|
try {
|
|
412
|
-
const
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
{
|
|
417
|
-
uid: `${Date.now()}_${Math.random()}`,
|
|
526
|
+
const res = await onUploading(file);
|
|
527
|
+
if (res) {
|
|
528
|
+
newAttachments.push({
|
|
529
|
+
id: res.id,
|
|
418
530
|
name: file.name,
|
|
419
531
|
size: (file as any).size,
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
532
|
+
});
|
|
533
|
+
}
|
|
534
|
+
} catch (err) {
|
|
535
|
+
console.error(err);
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
setLocalAttachments([...localAttachments, ...newAttachments]);
|
|
539
|
+
onUpdateAttachments &&
|
|
540
|
+
onUpdateAttachments([...localAttachments, ...newAttachments]);
|
|
429
541
|
};
|
|
430
|
-
const removeAttachment = (
|
|
431
|
-
const next = localAttachments.filter((a) => a.
|
|
542
|
+
const removeAttachment = (id: string) => {
|
|
543
|
+
const next = localAttachments.filter((a) => a.id !== id);
|
|
432
544
|
setLocalAttachments(next);
|
|
433
545
|
onUpdateAttachments && onUpdateAttachments(next);
|
|
434
546
|
};
|
|
@@ -440,19 +552,19 @@ export const ChatInput = React.forwardRef<
|
|
|
440
552
|
const text = (localValue || "").trim();
|
|
441
553
|
if (!text) return;
|
|
442
554
|
const data = {
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
),
|
|
555
|
+
message: text,
|
|
556
|
+
agents: selectedAgent.map((it) => ({ id: it.id, name: it.name })),
|
|
557
|
+
files: localAttachments.map((file) => ({
|
|
558
|
+
id: file.id,
|
|
559
|
+
name: file.name,
|
|
560
|
+
extension: file.name.substring(file.name.lastIndexOf(".")),
|
|
561
|
+
})),
|
|
450
562
|
};
|
|
451
563
|
onSubmit && onSubmit(data);
|
|
452
564
|
setLocalValue("");
|
|
453
565
|
};
|
|
454
566
|
const overlay = (
|
|
455
|
-
<
|
|
567
|
+
<AgentListDropdownContent>
|
|
456
568
|
<ul className="agent-list">
|
|
457
569
|
{agentList.map((item) => (
|
|
458
570
|
<li key={String(item.id)}>
|
|
@@ -460,17 +572,22 @@ export const ChatInput = React.forwardRef<
|
|
|
460
572
|
</li>
|
|
461
573
|
))}
|
|
462
574
|
</ul>
|
|
463
|
-
</
|
|
575
|
+
</AgentListDropdownContent>
|
|
464
576
|
);
|
|
465
577
|
return (
|
|
466
|
-
<Wrapper>
|
|
578
|
+
<Wrapper style={style}>
|
|
467
579
|
<div className="chat-input">
|
|
468
580
|
<div className="input-stack">
|
|
469
581
|
{localAttachments.length > 0 && (
|
|
470
582
|
<div className="attachment-bar">
|
|
471
583
|
{localAttachments.map((a) => (
|
|
472
|
-
<div className="attachment-card">
|
|
473
|
-
|
|
584
|
+
<div key={a.id} className="attachment-card">
|
|
585
|
+
{a.name.endsWith(".xlsx") ? (
|
|
586
|
+
<IconFont type="icon-excel" />
|
|
587
|
+
) : (
|
|
588
|
+
<IconFont type="icon-audio" />
|
|
589
|
+
)}
|
|
590
|
+
|
|
474
591
|
<Typography.Text
|
|
475
592
|
className="name"
|
|
476
593
|
ellipsis={{ tooltip: a.name }}
|
|
@@ -479,7 +596,7 @@ export const ChatInput = React.forwardRef<
|
|
|
479
596
|
</Typography.Text>
|
|
480
597
|
<a
|
|
481
598
|
className="remove"
|
|
482
|
-
onClick={() => removeAttachment(a.
|
|
599
|
+
onClick={() => removeAttachment(a.id)}
|
|
483
600
|
>
|
|
484
601
|
<DeleteOutlined />
|
|
485
602
|
</a>
|
|
@@ -499,15 +616,6 @@ export const ChatInput = React.forwardRef<
|
|
|
499
616
|
))}
|
|
500
617
|
</div>
|
|
501
618
|
)}
|
|
502
|
-
{showTitle && (
|
|
503
|
-
<Input
|
|
504
|
-
className="title-input"
|
|
505
|
-
placeholder="请输入报告标题(可选)"
|
|
506
|
-
disabled={disabled || sending}
|
|
507
|
-
value={localTitle}
|
|
508
|
-
onChange={onTitleChange}
|
|
509
|
-
/>
|
|
510
|
-
)}
|
|
511
619
|
<Input.TextArea
|
|
512
620
|
ref={inputRef}
|
|
513
621
|
className="input textarea-stacked"
|
|
@@ -521,43 +629,47 @@ export const ChatInput = React.forwardRef<
|
|
|
521
629
|
</div>
|
|
522
630
|
<div className="footer">
|
|
523
631
|
<div className="left">
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
632
|
+
{!!agentList?.length && (
|
|
633
|
+
<Dropdown
|
|
634
|
+
trigger={["click"]}
|
|
635
|
+
popupRender={() => overlay}
|
|
636
|
+
placement="topLeft"
|
|
637
|
+
styles={{
|
|
638
|
+
root: {
|
|
639
|
+
boxShadow: "var(--ant-box-shadow-card)",
|
|
640
|
+
},
|
|
641
|
+
}}
|
|
642
|
+
>
|
|
643
|
+
<Tooltip title="选择助理">
|
|
644
|
+
<Button
|
|
645
|
+
className="agent-trigger"
|
|
646
|
+
onClick={(e) => e.preventDefault()}
|
|
647
|
+
>
|
|
648
|
+
<IconFont type="icon-at" />
|
|
649
|
+
</Button>
|
|
650
|
+
</Tooltip>
|
|
651
|
+
</Dropdown>
|
|
652
|
+
)}
|
|
653
|
+
{onUploading && (
|
|
654
|
+
<>
|
|
655
|
+
<Tooltip title="上传文件">
|
|
656
|
+
<Button
|
|
657
|
+
className="attach-upload"
|
|
658
|
+
onClick={() => setUploadModalOpen(true)}
|
|
659
|
+
disabled={disabled || sending}
|
|
660
|
+
>
|
|
661
|
+
<IconFont type="icon-paper-clip" />
|
|
662
|
+
</Button>
|
|
663
|
+
</Tooltip>
|
|
664
|
+
<FileUploadModal
|
|
665
|
+
open={uploadModalOpen}
|
|
666
|
+
onCancel={() => setUploadModalOpen(false)}
|
|
667
|
+
onOk={handleUploadFiles}
|
|
668
|
+
allowedExtensions={ALLOWED_EXTENSIONS}
|
|
669
|
+
allowedMimeTypes={ALLOWED_MIME_TYPES}
|
|
558
670
|
/>
|
|
559
|
-
|
|
560
|
-
|
|
671
|
+
</>
|
|
672
|
+
)}
|
|
561
673
|
</div>
|
|
562
674
|
<div style={{ display: "flex", alignItems: "center", gap: 6 }}>
|
|
563
675
|
{!isMobile && (
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { Space } from "antd";
|
|
2
|
+
import React, { forwardRef, useImperativeHandle, useRef } from "react";
|
|
3
|
+
import styled from "styled-components";
|
|
4
|
+
import { PaneHeader } from "./PaneHeader";
|
|
5
|
+
|
|
6
|
+
const Root = styled.div`
|
|
7
|
+
display: flex;
|
|
8
|
+
flex-direction: column;
|
|
9
|
+
height: 100%;
|
|
10
|
+
.body {
|
|
11
|
+
flex: 1 1 auto;
|
|
12
|
+
display: flex;
|
|
13
|
+
flex-direction: column;
|
|
14
|
+
gap: 12px;
|
|
15
|
+
padding: 12px;
|
|
16
|
+
overflow: auto;
|
|
17
|
+
}
|
|
18
|
+
`;
|
|
19
|
+
|
|
20
|
+
type DatasetPanelType = {
|
|
21
|
+
renderNode: React.ForwardRefExoticComponent<
|
|
22
|
+
any &
|
|
23
|
+
React.RefAttributes<{
|
|
24
|
+
reload: () => void;
|
|
25
|
+
handleAdd: () => void;
|
|
26
|
+
}>
|
|
27
|
+
>;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const DatasetPanel = React.forwardRef<
|
|
31
|
+
{ reload: () => void },
|
|
32
|
+
DatasetPanelType
|
|
33
|
+
>(({ renderNode: DatasetPanelComponent }, forwardRef) => {
|
|
34
|
+
const ref = useRef<{ reload: () => void; handleAdd: () => void }>(null);
|
|
35
|
+
|
|
36
|
+
const handleAdd = () => {
|
|
37
|
+
ref.current?.handleAdd();
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
useImperativeHandle(forwardRef, () => ({
|
|
41
|
+
reload,
|
|
42
|
+
}));
|
|
43
|
+
|
|
44
|
+
const reload = () => {
|
|
45
|
+
ref.current?.reload();
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<Root className="dataset-panel">
|
|
50
|
+
<PaneHeader
|
|
51
|
+
title="数据集"
|
|
52
|
+
extra={
|
|
53
|
+
<Space>
|
|
54
|
+
<a className="toolbar" onClick={handleAdd}>
|
|
55
|
+
+
|
|
56
|
+
</a>
|
|
57
|
+
</Space>
|
|
58
|
+
}
|
|
59
|
+
/>
|
|
60
|
+
<div className="body">
|
|
61
|
+
<DatasetPanelComponent ref={ref} />
|
|
62
|
+
</div>
|
|
63
|
+
</Root>
|
|
64
|
+
);
|
|
65
|
+
});
|
|
@@ -4,6 +4,7 @@ import styled from 'styled-components'
|
|
|
4
4
|
export type PaneHeaderProps = {
|
|
5
5
|
title?: string
|
|
6
6
|
extra?: React.ReactNode
|
|
7
|
+
style?: React.CSSProperties
|
|
7
8
|
}
|
|
8
9
|
|
|
9
10
|
const Header = styled.div`
|
|
@@ -24,9 +25,9 @@ const Header = styled.div`
|
|
|
24
25
|
}
|
|
25
26
|
`
|
|
26
27
|
|
|
27
|
-
export const PaneHeader: React.FC<PaneHeaderProps> = ({ title = '', extra }) => {
|
|
28
|
+
export const PaneHeader: React.FC<PaneHeaderProps> = ({ title = '', extra, style = {} }) => {
|
|
28
29
|
return (
|
|
29
|
-
<Header className="pane-header">
|
|
30
|
+
<Header className="pane-header" style={style}>
|
|
30
31
|
<span className="title">{title}</span>
|
|
31
32
|
<div className="extra">{extra}</div>
|
|
32
33
|
</Header>
|