用React實(shí)現(xiàn)一個(gè)類(lèi) chatGPT 的交互式問(wèn)答組件的方法詳解
API文檔
屬性名 | 描述 | 類(lèi)型 | 默認(rèn)值 |
---|---|---|---|
recommendList | 推薦模板列表 | string[] | undefined | null |
commonUseList | 常用模板列表 | string[] | undefined | null |
uploadProps | 文件上傳,同 antd Upload 組件 | { accept?: string; children?: ReactNode; maxCount?: number; multiple?: boolean; } | undefined | null |
autoCompleteProps | 輸入框自動(dòng)補(bǔ)全,同 antd AutoComplete 組件 | { options?: DefaultOptionType[]; onSearch?: ((value: string) => void); } | undefined | null |
onSend | 發(fā)送消息 | ((msg: IQuestion) => void) | undefined | null |
onMsgLike | 點(diǎn)贊回答 | ((msg: IQuestion) => void) | undefined | null |
onMsgNotLike | 點(diǎn)踩回答 | ((msg: IQuestion) => void) | undefined | null |
onRefresh | 刷新回答 | ((msg: IQuestion) => void) | undefined | null |
renderAvatar | 自定義頭像 | ((msg: IMessage) => ReactNode) | undefined | null |
renderTools | 自定義消息框底部操作欄 | ((msg: IMessage) => ReactNode) | undefined | null |
isAnimation | 是否開(kāi)啟消息動(dòng)畫(huà)效果 | boolean | undefined | null |
className | 自定義類(lèi)名 | boolean | undefined | null |
style | 自定義樣式 | CSSProperties | undefined | null |
loading | 加載狀態(tài) | boolean | undefined | null |
messages | 消息列表 | IMessage[] | undefined | null |
# 功能介紹 | |||
這個(gè)組件的主要功能主要包括: |
- 輸入框上傳附件
- 輸入框自動(dòng)補(bǔ)全
- 自定義消息操作欄
- 自定義頭像
- 模板調(diào)用
下面會(huì)挨個(gè)介紹功能
輸入框上傳文件
這個(gè)功能很簡(jiǎn)單就是支持輸入框上傳附件,然后會(huì)把附件和問(wèn)題一起丟給使用者,由使用者自己去調(diào)用api接口來(lái)獲取回答.上傳組件采用的是antd的Upload組件,API也一致.大致代碼如下:
import React from 'react'; import { Chat, useMessage, EMessageType } from './chat'; export default function () { const { msgProps } = useMessage( (question, lastAnswer) => { return new Promise((resolve, reject) => { const { content, fileList } = question; setTimeout(() => { resolve({ content: '\n\n' + (lastAnswer ? '## 我又想了一下 \n\n' : '') + content?.replace(/嗎/g, '呢').replace(/你/g, '我') + '\n\n' + fileList.map((item) => item.name).join(' ') + '\n\n' }); }, 2000); }); }, { uploadProps: { multiple: true }, defaultMsgs: [ { key: 1, type: EMessageType.AI, content: '快來(lái)和我對(duì)話吧', renderTools: () => null, isAnimation: false } ] } ); return ( <Chat {...msgProps} /> ); }
輸入框自動(dòng)補(bǔ)全
自動(dòng)補(bǔ)全采用的是antd的Autocomplete組件,API也一致,原理就是當(dāng)輸入框內(nèi)容改變時(shí)去請(qǐng)求關(guān)聯(lián)內(nèi)容然后改變Autocomplete的options,就能實(shí)現(xiàn)自動(dòng)補(bǔ)全啦.
import React, { useState } from 'react'; import { Chat, useMessage, EMessageType, IMessage } from './chat'; export default function () { const [options, setOptions] = useState<{ value: string }[]>([]); const handleSearch = (value: string) => { setOptions(!value ? [] : [{ value }, { value: value + value }, { value: value + value + value }]); }; const { msgProps } = useMessage( (question, lastAnswer) => { return new Promise((resolve, reject) => { const { content } = question; setTimeout(() => { resolve({ isAnimation: !!lastAnswer, content: '\n\n' + (lastAnswer ? '## 我又想了一下 \n\n' : '') + content?.replace(/嗎/g, '呢').replace(/你/g, '我') + '\n\n' }); }, 2000); }); }, { autoCompleteProps: { options, onSearch: handleSearch } } ); return ( <Chat {...msgProps} /> ); }
自定義消息操作欄
由于每條消息下方還有操作欄,默認(rèn)的有重新回答、點(diǎn)贊、點(diǎn)踩、復(fù)制等,所以提供了自定義的功能,如果不需要默認(rèn)的這些功能也可以關(guān)閉或者自定義.
import React from 'react'; import { Chat, useMessage, EMessageType, IMessage } from './chat'; export default function () { const { msgProps } = useMessage( (question, lastAnswer) => { return new Promise((resolve, reject) => { const { content } = question; setTimeout(() => { resolve({ content: '\n\n' + (lastAnswer ? '## 我又想了一下 \n\n' : '') + content?.replace(/嗎/g, '呢').replace(/你/g, '我') + '\n\n', renderTools: (msg: IMessage) => <div>點(diǎn)個(gè)贊吧</div> }); }, 2000); }); }, { renderTools: (msg: IMessage) => <div>這里是自定義操作欄</div>, defaultMsgs: [ { key: 1, type: EMessageType.AI, content: '快來(lái)和我對(duì)話吧', renderTools: () => null, isAnimation: false }, { key: 2, type: EMessageType.AI, content: '支持每條消息獨(dú)立設(shè)置操作欄', renderTools: (msg: IMessage) => <div>這里是消息獨(dú)立操作欄</div>, isAnimation: false } ] } ); return ( <BixiProvider locale={enUS}> <Chat {...msgProps} /> </BixiProvider> ); }
自定義頭像
既然是對(duì)話,那肯定得提供自定義頭像的功能啦,使用方式的話是傳入renderAvatar這個(gè)方法,通過(guò)傳入的消息類(lèi)型來(lái)判斷顯示那個(gè)頭像,效果如下
import React from 'react'; import { Chat, useMessage, EMessageType, IMessage } from './chat'; export default function () { const { msgProps } = useMessage( (question, lastAnswer) => { return new Promise((resolve, reject) => { const { content } = question; setTimeout(() => { resolve({ content: '\n\n' + (lastAnswer ? '## 我又想了一下 \n\n' : '') + content?.replace(/嗎/g, '呢').replace(/你/g, '我') }); }, 2000); }); }, { renderAvatar: (msg: IMessage) => <>{msg.type === EMessageType.AI ? '人工智障' : '大帥比'}</>, defaultMsgs: [ { key: 1, type: EMessageType.AI, content: '快來(lái)和我對(duì)話吧', renderTools: () => null, isAnimation: false }, { key: 2, type: EMessageType.Self, content: '你真的是人工智能嗎', isAnimation: false }, { key: 3, type: EMessageType.AI, content: '支持每條消息單獨(dú)設(shè)置頭像', isAnimation: false } ] } ); return ( <Chat {...msgProps} /> ); }
模板調(diào)用
這個(gè)功能是比賽要求的,需要給用戶提供一些模板,用戶點(diǎn)擊模板就可以快速搜索答案之類(lèi)的,在輸入框輸入“/”就可以喚醒模板了,實(shí)現(xiàn)方式也很簡(jiǎn)單,監(jiān)聽(tīng)輸入框值的改變,如果輸入值和“/”匹配就直接喚起模板就可以了.效果如下
import React from 'react'; import { Chat, useMessage, EMessageType, IMessage } from './chat'; export default function () { const { msgProps } = useMessage( (question, lastAnswer) => { return new Promise((resolve, reject) => { const { content } = question; setTimeout(() => { resolve({ content: '\n\n' + (lastAnswer ? '## 我又想了一下 \n\n' : '') + content?.replace(/嗎/g, '呢').replace(/你/g, '我') }); }, 2000); }); }, { recommendList: ['標(biāo)題生成', '文章續(xù)寫(xiě)', '文章潤(rùn)色', '文章大綱', '朋友圈文案', '活動(dòng)方案', '翻譯', '演講稿'], commonUseList: ['標(biāo)題生成', '朋友圈文案'], } ); return ( <Chat {...msgProps} /> ); }
自定義hook
除了上面的功能外,還對(duì)邏輯進(jìn)行了封裝,調(diào)用這個(gè)hook可以獲取到messages、onRefresh、onSend、loading這幾個(gè)主要的props,其他的props你也可以自己傳入. 這個(gè)自定義hook封裝了消息發(fā)送方法,消息刷新方法,組件loading狀態(tài),消息列表等主要邏輯.重新回答的原理是去消息列表中尋找之前最近的一條問(wèn)題,然后在此調(diào)用獲取回答的接口 代碼如下:
import { useState, useCallback } from 'react'; import { IMessage, IChatProps, EMessageType, IQuestion } from './model'; import { uniqueId } from 'lodash-es'; type IUseMessageOption = Omit<IChatProps, 'onSend' | 'onRefresh' | 'loading' | 'messages'> & { defaultMsgs: IMessage[]; }; type IService = (msg: IQuestion, lastAnswer?: IMessage) => Promise<IMessage>; export function useMessage( getMsg: IService, { defaultMsgs, ...props }: IUseMessageOption ): { msgProps: IChatProps; } { const [messageList, setMessageList] = useState<IMessage[]>(defaultMsgs || []); const [loading, setLoading] = useState(false); const onRefresh = useCallback( (item: IMessage) => { const index = messageList.findIndex((msg) => msg.key === item.key); if (index < 1) return; const lastQuestion = messageList .slice(0, index) .reverse() .find((msg) => msg.type === EMessageType.Self); if (!lastQuestion) return; setLoading(true); getMsg(lastQuestion, messageList[index]).then((res) => { setLoading(false); const key = `${EMessageType.AI}-${uniqueId()}`; messageList[index] = { ...res, key, type: EMessageType.AI }; setMessageList([...messageList]); }); }, [getMsg, messageList] ); const onSend = useCallback( (msg: IQuestion) => { setLoading(true); setMessageList((list) => list.concat({ ...msg, key: `${EMessageType.Self}-${uniqueId()}`, type: EMessageType.Self })); getMsg(msg).then((res) => { setLoading(false); const key = `${EMessageType.AI}-${uniqueId()}`; setMessageList((list) => list.concat({ ...res, key, type: EMessageType.AI })); }); }, [getMsg] ); return { msgProps: { messages: messageList, onRefresh, onSend, loading, ...props } }; }
使用方法
該組件使用起來(lái)很簡(jiǎn)單,調(diào)用useMessage這個(gè)hook,傳入api接口(需要返回promise)就可以了,至于其他的組件api也可以一并傳入,還支持傳入歷史消息列表.然后這個(gè)hook就會(huì)返回所有該組件所需要的props,包括消息發(fā)送方法,消息刷新方法,組件loading狀態(tài),消息列表等.是不是很方便呢,哈哈.
以上就是用React實(shí)現(xiàn)一個(gè)類(lèi) chatGPT 的交互式問(wèn)答組件的方法詳解的詳細(xì)內(nèi)容,更多關(guān)于React chatGPT問(wèn)答組件的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
React Native自定義Android的SSL證書(shū)鏈校驗(yàn)
這篇文章主要為大家介紹了React Native自定義Android的SSL證書(shū)鏈校驗(yàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10React實(shí)現(xiàn)導(dǎo)出excel文件的操作步驟
在React項(xiàng)目的TypeScript文件中,因?yàn)樵腏avaScript或TypeScript并沒(méi)有提供直接的Excel導(dǎo)出功能,常用的Excel導(dǎo)出方法通常涉及使用第三方庫(kù),本文介紹了React實(shí)現(xiàn)導(dǎo)出excel文件的操作步驟,需要的朋友可以參考下2024-12-12react結(jié)合typescript?封裝組件實(shí)例詳解
這篇文章主要為大家介紹了react結(jié)合typescript?封裝組件實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04