Skip to content

Commit bdaa7c5

Browse files
committed
✨ feat: add actions config & render
1 parent 22ccb93 commit bdaa7c5

File tree

4 files changed

+133
-63
lines changed

4 files changed

+133
-63
lines changed

package.json

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@ant-design/pro-chat",
3-
"version": "1.15.2",
3+
"version": "1.15.2-cannay.0",
44
"description": "a solution for ai chat",
55
"keywords": [
66
"ai",
@@ -70,6 +70,7 @@
7070
"dayjs": "^1.11.11",
7171
"emoji-regex": "^10.3.0",
7272
"fast-deep-equal": "^3.1.3",
73+
"idb": "^8.0.0",
7374
"immer": "^10.1.1",
7475
"lodash-es": "^4.17.21",
7576
"lucide-react": "^0.288.0",
@@ -80,6 +81,7 @@
8081
"react-intersection-observer": "^9.10.3",
8182
"react-layout-kit": "^1.9.0",
8283
"react-markdown": "^8.0.7",
84+
"uuid": "^10.0.0",
8385
"zustand": "^4.5.2",
8486
"zustand-utils": "^1.3.2"
8587
},
@@ -91,6 +93,7 @@
9193
"@types/lodash-es": "^4.17.12",
9294
"@types/react": "18.2.31",
9395
"@types/react-dom": "^18.3.0",
96+
"@types/uuid": "^10.0.0",
9497
"@umijs/lint": "^4.2.15",
9598
"@vitest/coverage-v8": "latest",
9699
"ai": "^2.2.37",

src/ProSender/demos/actionsRender.tsx

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { ProChat, ProSender } from '@ant-design/pro-chat';
2+
import { Card, Empty, Space } from 'antd';
3+
import { useTheme } from 'antd-style';
4+
5+
export default () => {
6+
const theme = useTheme();
7+
return (
8+
<div style={{ background: theme.colorBgLayout }}>
9+
<ProChat
10+
inputAreaRender={(_, onMessageSend) => {
11+
return (
12+
<ProSender
13+
actions={{
14+
actionsInfoRender: (defaultdom, fileList) => {
15+
if (!fileList || fileList.length === 0) {
16+
return <Empty />;
17+
}
18+
return (
19+
<Space>
20+
{fileList.map((item) => {
21+
console.log('item', item);
22+
23+
return <Card key={item.uid} style={{ width: 300 }} title={item.fileName} />;
24+
})}
25+
</Space>
26+
);
27+
},
28+
}}
29+
onSubmit={(message, fileList) => {
30+
console.log('onSubmit', message, fileList);
31+
onMessageSend('send');
32+
}}
33+
/>
34+
);
35+
}}
36+
/>
37+
</div>
38+
);
39+
};

src/ProSender/index.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ description: a ProSender
88

99
## Default
1010

11-
<code src="./demos/base.tsx"></code>
11+
<code src="./demos/base.tsx"></code> <code src="./demos/actionsRender.tsx"></code>

src/ProSender/index.tsx

+89-61
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { UploadOutlined } from '@ant-design/icons';
1+
import { FileImageOutlined, UploadOutlined } from '@ant-design/icons';
22
import { Sender } from '@ant-design/x';
33
import { SenderProps } from '@ant-design/x/es/sender/interface';
44
import {
@@ -13,18 +13,24 @@ import {
1313
} from 'antd';
1414
import { useContext, useEffect, useState } from 'react';
1515
import EnterTypeButton from './components/EnterTypeButton.tsx';
16-
import LocalStorageManager from './storageManager'; // 引入类文件
16+
import LocalStorageManager from './storageManager';
1717
import { useStyles } from './style';
1818

19+
type ActionsType = {
20+
actionsRender?: ([fileUpBtn, imgUpBtn]: Array<React.ReactNode>) => React.ReactNode;
21+
actionsInfoRender?: (defaultdom: React.ReactNode, []: Array<UploadFile>) => React.ReactNode;
22+
};
23+
1924
const ProSender = (
20-
props: SenderProps & {
25+
props: Omit<SenderProps, 'onSubmit'> & {
2126
className?: string;
2227
upload?: UploadProps;
2328
sender?: SenderProps;
29+
actions?: ActionsType;
2430
onSubmit?: (message: string, fileList?: UploadFile[]) => void;
2531
},
2632
) => {
27-
const { className, upload, sender, onSubmit } = props || {};
33+
const { className, upload, sender, onSubmit, actions } = props || {};
2834

2935
const { cx, styles } = useStyles();
3036
const { getPrefixCls } = useContext(ConfigProvider.ConfigContext);
@@ -38,61 +44,89 @@ const ProSender = (
3844
setFileList(upload?.fileList || upload?.defaultFileList || []);
3945
}, []);
4046

41-
const ProSenderActions = () => {
47+
const senderActionsRender = () => {
48+
const UploadCommanProps = {
49+
...upload,
50+
fileList: [],
51+
beforeUpload: (file) => {
52+
localStorageManager
53+
.storeFile(file)
54+
.then((key) => {
55+
const storedFiles = localStorageManager.getFiles([key]);
56+
setFileList((prevList) => [...prevList, ...storedFiles]);
57+
})
58+
.catch((error) => {
59+
message.error(error);
60+
});
61+
return false;
62+
},
63+
};
64+
65+
const fileUpBtn = (
66+
<Upload {...UploadCommanProps}>
67+
<Button icon={<UploadOutlined />} />
68+
</Upload>
69+
);
70+
71+
const imgUpBtn = (
72+
<Upload
73+
{...UploadCommanProps}
74+
listType="picture"
75+
beforeUpload={(file) => {
76+
if (file.type !== 'image/jpeg' && file.type !== 'image/png') {
77+
message.error('只能上传jpg/png格式的图片');
78+
return Upload.LIST_IGNORE;
79+
}
80+
UploadCommanProps.beforeUpload(file);
81+
}}
82+
>
83+
<Button icon={<FileImageOutlined />} />
84+
</Upload>
85+
);
86+
87+
if (actions?.actionsRender) {
88+
return actions.actionsRender([fileUpBtn, imgUpBtn]);
89+
}
90+
4291
return (
4392
<Space className={cx(styles.actions, `${prefixClass}-sender-actions`)}>
44-
<Upload
45-
{...upload}
46-
fileList={[]}
47-
beforeUpload={(file) => {
48-
console.log('file', file, localStorageManager);
49-
50-
localStorageManager
51-
.storeFile(file)
52-
.then((key) => {
53-
console.log('key', key);
54-
55-
const storedFiles = localStorageManager.getFiles([key]);
56-
setFileList((prevList) => [...prevList, ...storedFiles]);
57-
})
58-
.catch((error) => {
59-
message.error(error);
60-
});
61-
62-
return false;
63-
}}
64-
>
65-
<Button icon={<UploadOutlined />} />
66-
</Upload>
93+
{[fileUpBtn, imgUpBtn]}
6794
</Space>
6895
);
6996
};
7097

71-
const SenderFileInfo = () => {
72-
if (fileList && fileList.length > 0) {
73-
return (
74-
<div className={cx(styles.fileInfo, `${prefixClass}-sender-file-info`)}>
75-
<Upload
76-
{...upload}
77-
fileList={fileList}
78-
listType="picture"
79-
onRemove={(file) => {
80-
const result = localStorageManager.removeFiles([file.uid]);
81-
if (result[0].success) {
82-
setFileList((prevList) => prevList.filter((item) => item.uid !== file.uid));
83-
} else {
84-
message.error(result[0].error);
85-
}
86-
}}
87-
/>
88-
<Divider />
89-
</div>
90-
);
98+
const senderFileInfoRender = () => {
99+
const fileInputRender = () => {
100+
if (fileList && fileList.length > 0) {
101+
return (
102+
<div className={cx(styles.fileInfo, `${prefixClass}-sender-file-info`)}>
103+
<Upload
104+
{...upload}
105+
fileList={fileList}
106+
listType="picture"
107+
onRemove={(file) => {
108+
const result = localStorageManager.removeFiles([file.uid]);
109+
if (result[0].success) {
110+
setFileList((prevList) => prevList.filter((item) => item.uid !== file.uid));
111+
} else {
112+
message.error(result[0].error);
113+
}
114+
}}
115+
/>
116+
<Divider />
117+
</div>
118+
);
119+
}
120+
return <></>;
121+
};
122+
123+
if (actions?.actionsInfoRender) {
124+
return actions.actionsInfoRender(fileInputRender(), fileList);
91125
}
92-
return <></>;
126+
return fileInputRender();
93127
};
94128

95-
const SenderArea = () => {
129+
const senderAreaRender = () => {
96130
const { onSubmit: defaultSubmit } = sender || {};
97131
return (
98132
<Sender
@@ -116,18 +150,12 @@ const ProSender = (
116150
);
117151
};
118152

119-
const Wrapper = ({ children }) => {
120-
return (
121-
<div className={cx(styles.container, `${prefixClass}-sender`, className)}>{children}</div>
122-
);
123-
};
124-
125153
return (
126-
<Wrapper>
127-
<ProSenderActions />
128-
<SenderFileInfo />
129-
<SenderArea />
130-
</Wrapper>
154+
<div className={cx(styles.container, `${prefixClass}-sender`, className)}>
155+
{senderActionsRender()}
156+
{senderFileInfoRender()}
157+
{senderAreaRender()}
158+
</div>
131159
);
132160
};
133161

0 commit comments

Comments
 (0)