|  | 
|  | 1 | +import React, { useEffect, useState } from 'react'; | 
|  | 2 | +import { LikeOutlined } from '@ant-design/icons'; | 
|  | 3 | +import { Button } from 'antd'; | 
|  | 4 | +import { Chat, Flex } from 'dt-react-component'; | 
|  | 5 | +import { cloneDeep } from 'lodash-es'; | 
|  | 6 | + | 
|  | 7 | +import { ConversationProperties } from '../../entity'; | 
|  | 8 | +import { mockSSE } from '../mockSSE'; | 
|  | 9 | + | 
|  | 10 | +export default function () { | 
|  | 11 | +    const chat = Chat.useChat(); | 
|  | 12 | +    const [value, setValue] = useState<string | undefined>(''); | 
|  | 13 | + | 
|  | 14 | +    const [convert, setConvert] = useState(false); | 
|  | 15 | + | 
|  | 16 | +    const [data, setData] = React.useState<ConversationProperties[]>([]); | 
|  | 17 | + | 
|  | 18 | +    const [selectId, setSelectId] = React.useState<string | undefined>('1'); | 
|  | 19 | +    const [expand, setIsExpand] = React.useState(true); | 
|  | 20 | + | 
|  | 21 | +    const handleSelectChat = (conversation: ConversationProperties) => { | 
|  | 22 | +        setSelectId(conversation.id); | 
|  | 23 | +    }; | 
|  | 24 | + | 
|  | 25 | +    const handleRename = (_conversation: ConversationProperties, _value: string) => { | 
|  | 26 | +        return Promise.resolve(true); | 
|  | 27 | +    }; | 
|  | 28 | + | 
|  | 29 | +    const handleClearChat = (conversation: ConversationProperties) => { | 
|  | 30 | +        const list = cloneDeep(data).filter((i) => i.id !== conversation.id); | 
|  | 31 | +        if (conversation.id === chat.conversation.get()?.id) { | 
|  | 32 | +            chat.conversation.remove(); | 
|  | 33 | +            if (list.length) { | 
|  | 34 | +                handleSelectChat(list[0]); | 
|  | 35 | +                chat.conversation.create({ ...list[0] }); | 
|  | 36 | +            } | 
|  | 37 | +        } | 
|  | 38 | +        setData(list); | 
|  | 39 | +    }; | 
|  | 40 | +    const handleNewChat = () => { | 
|  | 41 | +        chat.conversation.remove(); | 
|  | 42 | +        chat.conversation.create({ id: new Date().valueOf().toString() }); | 
|  | 43 | +    }; | 
|  | 44 | + | 
|  | 45 | +    const addData = (str: string) => { | 
|  | 46 | +        setData((prev) => { | 
|  | 47 | +            const idx = prev.length + 1; | 
|  | 48 | +            return [ | 
|  | 49 | +                ...prev, | 
|  | 50 | +                { | 
|  | 51 | +                    id: chat.conversation.get()!.id, | 
|  | 52 | +                    title: str, | 
|  | 53 | +                    assistantId: idx.toString(), | 
|  | 54 | +                    createdAt: new Date().valueOf(), | 
|  | 55 | +                    updatedAt: new Date().valueOf(), | 
|  | 56 | +                }, | 
|  | 57 | +            ]; | 
|  | 58 | +        }); | 
|  | 59 | +        handleSelectChat(chat.conversation.get()!); | 
|  | 60 | +    }; | 
|  | 61 | + | 
|  | 62 | +    const handleSubmit = (raw = value) => { | 
|  | 63 | +        const val = raw?.trim(); | 
|  | 64 | +        if (chat.loading() || !val) return; | 
|  | 65 | +        setValue(''); | 
|  | 66 | +        const promptId = new Date().valueOf().toString(); | 
|  | 67 | +        const messageId = (new Date().valueOf() + 1).toString(); | 
|  | 68 | +        chat.prompt.create({ id: promptId, title: val }); | 
|  | 69 | +        chat.message.create(promptId, { id: messageId, content: '' }); | 
|  | 70 | +        mockSSE({ | 
|  | 71 | +            message: val, | 
|  | 72 | +            onopen() { | 
|  | 73 | +                chat.start(promptId, messageId); | 
|  | 74 | +                addData(val); | 
|  | 75 | +            }, | 
|  | 76 | +            onmessage(str) { | 
|  | 77 | +                chat.push(promptId, messageId, str); | 
|  | 78 | +            }, | 
|  | 79 | +            onstop() { | 
|  | 80 | +                chat.close(promptId, messageId); | 
|  | 81 | +            }, | 
|  | 82 | +        }); | 
|  | 83 | +    }; | 
|  | 84 | + | 
|  | 85 | +    useEffect(() => { | 
|  | 86 | +        chat.conversation.create({ id: new Date().valueOf().toString() }); | 
|  | 87 | +    }, []); | 
|  | 88 | + | 
|  | 89 | +    return ( | 
|  | 90 | +        <div style={{ width: '100%', height: 600, display: 'flex', flexDirection: 'column' }}> | 
|  | 91 | +            <Chat | 
|  | 92 | +                chat={chat} | 
|  | 93 | +                codeBlock={{ | 
|  | 94 | +                    convert, | 
|  | 95 | +                }} | 
|  | 96 | +                messageIcons={() => <LikeOutlined className="dtc__message__icon" />} | 
|  | 97 | +                components={{ | 
|  | 98 | +                    a: ({ children }) => ( | 
|  | 99 | +                        <Button | 
|  | 100 | +                            type="primary" | 
|  | 101 | +                            size="small" | 
|  | 102 | +                            ghost | 
|  | 103 | +                            onClick={() => setConvert((p) => !p)} | 
|  | 104 | +                        > | 
|  | 105 | +                            {children} | 
|  | 106 | +                        </Button> | 
|  | 107 | +                    ), | 
|  | 108 | +                }} | 
|  | 109 | +            > | 
|  | 110 | +                <Chat.Group | 
|  | 111 | +                    loading={false} | 
|  | 112 | +                    expand={expand} | 
|  | 113 | +                    fullscreen | 
|  | 114 | +                    data={data} | 
|  | 115 | +                    openFloat={false} | 
|  | 116 | +                    listProps={{ | 
|  | 117 | +                        selectId, | 
|  | 118 | +                        onRename: handleRename, | 
|  | 119 | +                        onDelete: handleClearChat, | 
|  | 120 | +                        onItemClick: handleSelectChat, | 
|  | 121 | +                    }} | 
|  | 122 | +                    dialogButtonProps={{ | 
|  | 123 | +                        onClick: handleNewChat, | 
|  | 124 | +                    }} | 
|  | 125 | +                    onExpandChange={setIsExpand} | 
|  | 126 | +                > | 
|  | 127 | +                    <Chat.Content | 
|  | 128 | +                        data={chat.conversation.get()?.prompts || []} | 
|  | 129 | +                        placeholder={ | 
|  | 130 | +                            <div className="dtc__aigc__content__inner__holder"> | 
|  | 131 | +                                <Chat.Welcome | 
|  | 132 | +                                    title="dt-react-component" | 
|  | 133 | +                                    description="React UI component library based on antd package" | 
|  | 134 | +                                /> | 
|  | 135 | +                                <br /> | 
|  | 136 | +                                <Flex vertical align="start" gap="4px"> | 
|  | 137 | +                                    <Chat.Tag onClick={() => handleSubmit('请告诉我一首诗')}> | 
|  | 138 | +                                        返回一首诗 | 
|  | 139 | +                                    </Chat.Tag> | 
|  | 140 | +                                    <Chat.Tag onClick={() => handleSubmit('生成 CodeBlock')}> | 
|  | 141 | +                                        生成 CodeBlock | 
|  | 142 | +                                    </Chat.Tag> | 
|  | 143 | +                                </Flex> | 
|  | 144 | +                            </div> | 
|  | 145 | +                        } | 
|  | 146 | +                    /> | 
|  | 147 | +                    <Chat.Input | 
|  | 148 | +                        value={value} | 
|  | 149 | +                        onChange={setValue} | 
|  | 150 | +                        onPressEnter={() => handleSubmit()} | 
|  | 151 | +                        onPressShiftEnter={() => setValue((v) => v + '\n')} | 
|  | 152 | +                        button={{ | 
|  | 153 | +                            disabled: chat.loading() || !value?.trim(), | 
|  | 154 | +                        }} | 
|  | 155 | +                        placeholder="请输入想咨询的内容…" | 
|  | 156 | +                    /> | 
|  | 157 | +                </Chat.Group> | 
|  | 158 | +            </Chat> | 
|  | 159 | +        </div> | 
|  | 160 | +    ); | 
|  | 161 | +} | 
0 commit comments