From 6bbe254ee654c0c9198eccb2bed9caab55670e4a Mon Sep 17 00:00:00 2001 From: yingying Date: Thu, 8 Aug 2024 13:07:41 +0800 Subject: [PATCH] feat: enabel to send img --- client/package.json | 2 +- client/yarn.lock | 78 +++---- extension/package.json | 2 +- lui/package.json | 2 +- lui/src/Chat/components/InputAreaRender.tsx | 216 ++++++++++++++++++ lui/src/Chat/index.tsx | 95 ++++++-- lui/src/Chat/inputArea/InputArea.tsx | 96 -------- lui/src/Chat/inputArea/actions.tsx | 39 ---- lui/src/icons/DeleteIcon.tsx | 17 ++ lui/src/interface/contentMessage.interface.ts | 6 +- 10 files changed, 358 insertions(+), 195 deletions(-) create mode 100644 lui/src/Chat/components/InputAreaRender.tsx delete mode 100644 lui/src/Chat/inputArea/InputArea.tsx delete mode 100644 lui/src/Chat/inputArea/actions.tsx create mode 100644 lui/src/icons/DeleteIcon.tsx diff --git a/client/package.json b/client/package.json index fd432d81..8cde5047 100644 --- a/client/package.json +++ b/client/package.json @@ -39,7 +39,7 @@ "lottie-react": "^2.4.0", "next": "14.0.1", "openai": "^4.24.7", - "petercat-lui": "^0.1.1", + "petercat-lui": "^0.1.2", "postcss": "8.4.27", "react": "18.2.0", "react-dom": "18.2.0", diff --git a/client/yarn.lock b/client/yarn.lock index 15679717..34eb713e 100644 --- a/client/yarn.lock +++ b/client/yarn.lock @@ -49,7 +49,7 @@ rc-util "^5.35.0" stylis "^4.0.13" -"@ant-design/fast-color@^2.0.1": +"@ant-design/fast-color@^2.0.6": version "2.0.6" resolved "https://registry.npmjs.org/@ant-design/fast-color/-/fast-color-2.0.6.tgz#ab4d4455c1542c9017d367c2fa8ca3e4215d0ba2" integrity sha512-y2217gk4NqL35giHl72o6Zzqji9O7vHh9YmhUVkPtAOpoTCH4uWxo/pr4VE8t0+ChEPs0qo4eJRC5Q1eXWo3vA== @@ -1874,11 +1874,11 @@ integrity sha512-jktYRmZwmau63adUG3GKOAVCofBXkk55S/zQ94XOorAHhwqFIOFAy1rSp2N0Wp6/tGbe9V3u/ExlGZypyY17rg== "@floating-ui/core@^1.6.0": - version "1.6.6" - resolved "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.6.tgz#f6edf703c8acb73e3802cf558c88ddb7cddc4f67" - integrity sha512-Vkvsw6EcpMHjvZZdMkSY+djMGFbt7CRssW99Ne8tar2WLnZ/l3dbxeTShbLQj+/s35h+Qb4cmnob+EzwtjrXGQ== + version "1.6.7" + resolved "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.7.tgz#7602367795a390ff0662efd1c7ae8ca74e75fb12" + integrity sha512-yDzVT/Lm101nQ5TCVeK65LtdN7Tj4Qpr9RTXJ2vPFLqtLxwOrpoxAHAJI8J3yYWUc40J0BDBheaitK5SJmno2g== dependencies: - "@floating-ui/utils" "^0.2.6" + "@floating-ui/utils" "^0.2.7" "@floating-ui/dom@^0.4.5": version "0.4.5" @@ -1888,12 +1888,12 @@ "@floating-ui/core" "^0.6.2" "@floating-ui/dom@^1.0.0": - version "1.6.9" - resolved "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.9.tgz#7240f4fea0ff929a9d642f7572331d33dd2ee809" - integrity sha512-zB1PcI350t4tkm3rvUhSRKa9sT7vH5CrAbQxW+VaPYJXKAO0gsg4CTueL+6Ajp7XzAQC8CW4Jj1Wgqc0sB6oUQ== + version "1.6.10" + resolved "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.10.tgz#b74c32f34a50336c86dcf1f1c845cf3a39e26d6f" + integrity sha512-fskgCFv8J8OamCmyun8MfjB1Olfn+uZKjOKZ0vhYF3gRmEUXcGOjxWL8bBr7i4kIuPZ2KD2S3EUIOxnjC8kl2A== dependencies: "@floating-ui/core" "^1.6.0" - "@floating-ui/utils" "^0.2.6" + "@floating-ui/utils" "^0.2.7" "@floating-ui/react-dom-interactions@^0.3.1": version "0.3.1" @@ -1929,10 +1929,10 @@ aria-hidden "^1.2.3" tabbable "^6.0.1" -"@floating-ui/utils@^0.2.6": - version "0.2.6" - resolved "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.6.tgz#1898a31c7e17a50384147a02a4e6264b1b1a0291" - integrity sha512-0KI3zGxIUs1KDR/pjQPdJH4Z8nGBm0yJ5WRoRfdw1Kzeh45jkIfA0rmD0kBF6fKHH+xaH7g8y4jIXyAV5MGK3g== +"@floating-ui/utils@^0.2.7": + version "0.2.7" + resolved "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.7.tgz#d0ece53ce99ab5a8e37ebdfe5e32452a2bfc073e" + integrity sha512-X8R8Oj771YRl/w+c1HqAC1szL8zWQRwFvgDwT129k9ACdBoud/+/rX9V0qiMl6LWUdP9voC2nDVZYPMQQsb6eA== "@formatjs/ecma402-abstract@2.0.0": version "2.0.0" @@ -3234,11 +3234,11 @@ "@babel/runtime" "^7.24.4" "@rc-component/color-picker@~2.0.0": - version "2.0.0" - resolved "https://registry.npmjs.org/@rc-component/color-picker/-/color-picker-2.0.0.tgz#3bac931f53757bcc9ed3c57cfc8264c25e6e684a" - integrity sha512-52z3XqUwUr0+Br3B8RjN2GfuR1Pk3MZPAVd34WptWFEOyTz7OQmmn8nqgXUBOYwZem8jXp6G3iv+6Dm1+1epJA== + version "2.0.1" + resolved "https://registry.npmjs.org/@rc-component/color-picker/-/color-picker-2.0.1.tgz#6b9b96152466a9d4475cbe72b40b594bfda164be" + integrity sha512-WcZYwAThV/b2GISQ8F+7650r5ZZJ043E57aVBFkQ+kSY4C6wdofXgB0hBx+GPGpIU0Z81eETNoDUJMr7oy/P8Q== dependencies: - "@ant-design/fast-color" "^2.0.1" + "@ant-design/fast-color" "^2.0.6" "@babel/runtime" "^7.23.6" classnames "^2.2.6" rc-util "^5.38.1" @@ -6871,9 +6871,9 @@ camelcase@^5.3.1: integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== caniuse-lite@^1.0.30001406, caniuse-lite@^1.0.30001464, caniuse-lite@^1.0.30001646: - version "1.0.30001649" - resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001649.tgz#3ec700309ca0da2b0d3d5fb03c411b191761c992" - integrity sha512-fJegqZZ0ZX8HOWr6rcafGr72+xcgJKI9oWfDW5DrD7ExUtgZC7a7R7ZYmZqplh7XDocFdGeIFn7roAxhOeYrPQ== + version "1.0.30001650" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001650.tgz#dd1eba0938e39536d184c3c99b2569a13788bc16" + integrity sha512-fgEc7hP/LB7iicdXHUI9VsBsMZmUmlVJeQP2qqQW+3lkqVhbmjEU8zp+h5stWeilX+G7uXuIUIIlWlDw9jdt8g== ccount@^2.0.0: version "2.0.1" @@ -8782,9 +8782,9 @@ for-each@^0.3.3: is-callable "^1.1.3" foreground-child@^3.1.0: - version "3.2.1" - resolved "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz#767004ccf3a5b30df39bed90718bab43fe0a59f7" - integrity sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA== + version "3.3.0" + resolved "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz#0ac8644c06e431439f8561db8ecf29a7b5519c77" + integrity sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg== dependencies: cross-spawn "^7.0.0" signal-exit "^4.0.1" @@ -11573,9 +11573,9 @@ open@^9.1.0: is-wsl "^2.2.0" openai@^4.17.0, openai@^4.24.7: - version "4.55.0" - resolved "https://registry.npmjs.org/openai/-/openai-4.55.0.tgz#d28b5a0b97214de4a2f018efd4665468e6c1fd94" - integrity sha512-BR3TUybzdqNeBMgEFvxgBrFks9FY2NoP2jyTf7LT4UxPv8chevRKSxKezsINVSeQ/QLA12CALR1oco6KVdVpVA== + version "4.55.1" + resolved "https://registry.npmjs.org/openai/-/openai-4.55.1.tgz#59fe4565ab117cf869137588f6da15ef330e405f" + integrity sha512-FziYJcWl+SAGbt5AcRIzVzNcnKohpEMQdtzVOmHFbBp/if7x2+ACqgxF2XUbyi2PcKONPcVpmtG5h9qoDAEXwQ== dependencies: "@types/node" "^18.11.18" "@types/node-fetch" "^2.6.4" @@ -11821,10 +11821,10 @@ pbkdf2@^3.0.3, pbkdf2@^3.1.2: safe-buffer "^5.0.1" sha.js "^2.4.8" -petercat-lui@^0.1.1: - version "0.1.1" - resolved "https://registry.npmjs.org/petercat-lui/-/petercat-lui-0.1.1.tgz#3cb9bc0f5097ae1ed209a37c5d8288d183c70be5" - integrity sha512-+AVynsO72fWoffz/fOXSq3FWClHMgev7H64eGMGXZ+nOc+JGcOHl304GKaTpLptgCNw9ROSOcgsq2rm798IYQg== +petercat-lui@^0.1.2: + version "0.1.2" + resolved "https://registry.npmjs.org/petercat-lui/-/petercat-lui-0.1.2.tgz#2d0d153d71542c7540a28be0e8389bd8024e1f4d" + integrity sha512-gnmZJoEg+C7Ii7LIcmgPpuvrYOlj2tCXnx8OYh8f1wFr+aAW4xdgvy3Rb+ZAMVRxaf4SyBaFAXvcJoAtl1UkJg== dependencies: "@ant-design/icons" "^5.3.5" "@ant-design/pro-chat" "^1.9.0" @@ -12566,9 +12566,9 @@ rc-input-number@~9.2.0: rc-util "^5.40.1" rc-input@~1.6.0, rc-input@~1.6.2: - version "1.6.2" - resolved "https://registry.npmjs.org/rc-input/-/rc-input-1.6.2.tgz#bb356a3b8af421beb7ff26d54ebf054396dfe447" - integrity sha512-nJqsiIv8K88w8pvbUR5savKqBokdSR0zVGPntLApeOKFp8dp6s92l1CzD60yVActpCZAJwlCfRX5rno+QVYV7g== + version "1.6.3" + resolved "https://registry.npmjs.org/rc-input/-/rc-input-1.6.3.tgz#f1708fc3d5e68f95cb20faeb3eed1df8543cd444" + integrity sha512-wI4NzuqBS8vvKr8cljsvnTUqItMfG1QbJoxovCgL+DX4eVUcHIjVwharwevIxyy7H/jbLryh+K7ysnJr23aWIA== dependencies: "@babel/runtime" "^7.11.1" classnames "^2.2.1" @@ -14133,9 +14133,9 @@ tailwindcss-scoped-preflight@^3.2.6: integrity sha512-4mtCR3qVdHJK0fikwleAaVPV2cl05r/ISQ0cceUowVBQSiHhHwRBqaB5zk97OXVeL7mgb/T44gVCBncuZROCNA== tailwindcss@^3.4.1, tailwindcss@^3.4.3: - version "3.4.7" - resolved "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.7.tgz#6092f18767f5933f59375b9afe558e592fc77201" - integrity sha512-rxWZbe87YJb4OcSopb7up2Ba4U82BoiSGUdoDr3Ydrg9ckxFS/YWsvhN323GMcddgU65QRy7JndC7ahhInhvlQ== + version "3.4.8" + resolved "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.8.tgz#74fdfc085732c244ad9ca4ee0d539bc5dddd58fd" + integrity sha512-GkP17r9GQkxgZ9FKHJQEnjJuKBcbFhMFzKu5slmN6NjlCuFnYJMQ8N4AZ6VrUyiRXlDtPKHkesuQ/MS913Nvdg== dependencies: "@alloc/quick-lru" "^5.2.0" arg "^5.0.2" @@ -14166,9 +14166,9 @@ tapable@^2.0.0, tapable@^2.2.0, tapable@^2.2.1: integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== terser@^5.10.0: - version "5.31.3" - resolved "https://registry.npmjs.org/terser/-/terser-5.31.3.tgz#b24b7beb46062f4653f049eea4f0cd165d0f0c38" - integrity sha512-pAfYn3NIZLyZpa83ZKigvj6Rn9c/vd5KfYGX7cN1mnzqgDcxWvrU5ZtAfIKhEXz9nRecw4z3LXkjaq96/qZqAA== + version "5.31.4" + resolved "https://registry.npmjs.org/terser/-/terser-5.31.4.tgz#60274c4d3e20eb9a6468526a8878aba8e8428c5f" + integrity sha512-3OU03GgblDgu0g+sdnsVzhBPxnjV+WJuMmocN1qBBZDQ3ia7jZQSAkePeKbPlYAejGXUTYe1CmSaUeV51mvaIw== dependencies: "@jridgewell/source-map" "^0.3.3" acorn "^8.8.2" diff --git a/extension/package.json b/extension/package.json index 644fb0bb..b59ca5b1 100644 --- a/extension/package.json +++ b/extension/package.json @@ -15,7 +15,7 @@ "mini-css-extract-plugin": "^2.9.0", "next": "14.2.5", "next-compose-plugins": "^2.2.1", - "petercat-lui": "^0.1.0", + "petercat-lui": "^0.1.2", "postcss-loader": "^8.1.1", "react": "^18", "react-dom": "^18", diff --git a/lui/package.json b/lui/package.json index 14a6ecf8..a32aaf44 100644 --- a/lui/package.json +++ b/lui/package.json @@ -1,6 +1,6 @@ { "name": "petercat-lui", - "version": "0.1.1", + "version": "0.1.2", "description": "A react library developed with dumi", "module": "dist/index.js", "types": "dist/index.d.ts", diff --git a/lui/src/Chat/components/InputAreaRender.tsx b/lui/src/Chat/components/InputAreaRender.tsx new file mode 100644 index 00000000..f7444478 --- /dev/null +++ b/lui/src/Chat/components/InputAreaRender.tsx @@ -0,0 +1,216 @@ +import { + message as AntMessage, + Button, + Form, + Image, + Input, + Space, + Tooltip, + Upload, +} from 'antd'; +import React, { useCallback, useMemo, useState } from 'react'; +import { DeleteIcon } from '../../icons/DeleteIcon'; +import { NewMessageIcon } from '../../icons/NewMessageIcon'; +import { SendMessageIcon } from '../../icons/SendMessageIcon'; +import { StopMessageIcon } from '../../icons/StopMessageIcon'; +import { UploadImageIcon } from '../../icons/UploadImageIcon'; +import { + ImageURLContentBlock, + MessageContent, + TextContentBlock, +} from '../../interface'; + +const InputAreaRender = (props: { + isShowStop: boolean; + onMessageSend: (message: string) => void | Promise; + onClear: () => void; + onStop: () => void; +}) => { + const [form] = Form.useForm(); + const [message, setMessage] = useState(''); + const [fileList, setFileList] = useState< + { url: string | ArrayBuffer | null; uid: any }[] + >([]); + + const disabled = useMemo(() => fileList?.length >= 4, [fileList]); + + const handleMessage = useCallback( + (text?: string) => { + if (!props || !props?.onMessageSend || (!text && !fileList.length)) { + return; + } + setMessage(''); + form.resetFields(); + let content: MessageContent[] = text + ? [ + { + type: 'text', + text: text, + } as TextContentBlock, + ] + : []; + if (fileList.length > 0) { + const images = fileList.map((file) => { + return { + type: 'image_url', + image_url: { + url: file.url, + detail: 'auto', + }, + } as ImageURLContentBlock; + }); + content = content.concat(images); + } + props.onMessageSend(JSON.stringify(content)); + setFileList([]); + }, + [props.onMessageSend, fileList], + ); + + const handleKeyDown = (event: React.KeyboardEvent) => { + if ( + event.key === 'Enter' && + !event.shiftKey && + !event.nativeEvent.isComposing + ) { + handleMessage(message); + } + }; + const handleChange = (event: React.ChangeEvent) => { + setMessage(event.target.value); + }; + + const handleUpload = ({ file, uid }: { file: File | null; uid: string }) => { + if (!file || disabled) { + return; + } + if (fileList.length >= 4) { + AntMessage.warning('上传图片不能超过 4 张'); + return; + } + const reader = new FileReader(); + reader.onload = () => { + setFileList([...fileList, { url: reader.result, uid }]); + }; + reader.readAsDataURL(file); + }; + + const handleRemove = (uid: string) => { + setFileList(fileList.filter((item) => item.uid !== uid)); + }; + + const handlePaste = (event: React.ClipboardEvent) => { + const clipboardItems = event.clipboardData.items; + for (let i = 0; i < clipboardItems.length; i++) { + const item = clipboardItems[i]; + if (item.type.includes('image')) { + const file = item.getAsFile(); + handleUpload({ file, uid: Date.now().toString() }); + } + } + }; + + return ( +
+ + + +
+
+ + {props && props.isShowStop && ( +
+ } + /> + + + {fileList.map((file) => ( +
+ uploaded +
handleRemove(file.uid)} + > + +
+
+ ))} + +
+
- )} - - - - - - - ); -}; -export default InputAreaRender; diff --git a/lui/src/Chat/inputArea/actions.tsx b/lui/src/Chat/inputArea/actions.tsx deleted file mode 100644 index 5ad6d9f3..00000000 --- a/lui/src/Chat/inputArea/actions.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import { - ItalicOutlined, - PlusSquareOutlined, - ToolOutlined, -} from '@ant-design/icons'; -import { Button, ConfigProvider } from 'antd'; -import React from 'react'; - -const buttonTheme = { - components: { - Button: { - defaultBg: 'rgba(0, 0, 0, 0.06)', - defaultHoverBg: 'rgb(222,222,222)', - defaultHoverColor: 'rgba(0, 0, 0, 0.88)', - }, - }, -}; - -const Actions: React.FC = () => { - return ( -
- -
-
-
-
-
-
- ); -}; - -export default Actions; diff --git a/lui/src/icons/DeleteIcon.tsx b/lui/src/icons/DeleteIcon.tsx new file mode 100644 index 00000000..52f30974 --- /dev/null +++ b/lui/src/icons/DeleteIcon.tsx @@ -0,0 +1,17 @@ +import React from 'react'; + +export const DeleteIcon = () => ( + + + +); + diff --git a/lui/src/interface/contentMessage.interface.ts b/lui/src/interface/contentMessage.interface.ts index 0ea0ae09..3ee0700e 100644 --- a/lui/src/interface/contentMessage.interface.ts +++ b/lui/src/interface/contentMessage.interface.ts @@ -41,17 +41,17 @@ interface ImageURL { detail?: 'auto' | 'low' | 'high'; } -interface ImageURLContentBlock { +export interface ImageURLContentBlock { image_url: ImageURL; type: 'image_url'; } -interface TextContentBlock { +export interface TextContentBlock { text: string; type: 'text'; } -type MessageContent = ImageURLContentBlock | TextContentBlock; +export type MessageContent = ImageURLContentBlock | TextContentBlock; export interface Message { role: string;