index.tsx 8.12 KB
import React, {useState, useEffect, useRef} from "react";
import './style.less'
import { Input, Button } from '@chatui/core';
import Markdown from '@/components/deepSeekIndex/Markdown'
import banner from "./banner_base.png";
import bg from "./bg_base.jpg";
import refresh from "./refresh.png";
import _ from 'lodash';

export const getTime = () => {
    // 创建 Date 对象
    const now = new Date();

    // 获取月份(0-11,需 +1 转为实际月份)
    const month = String(now.getMonth() + 1).padStart(2, '0'); // 补零成两位数
    // 获取日期
    const day = String(now.getDate()).padStart(2, '0');
    // 获取小时
    const hours = String(now.getHours()).padStart(2, '0');
    // 获取分钟
    const minutes = String(now.getMinutes()).padStart(2, '0');
    // 组合成目标格式
    const result = `${month}月${day}日 ${hours}:${minutes}`;

    console.log(result); // 示例输出:07月15日 08:30

    return result;
}
const example_1 = [
    {
        name: '联通提供哪些服务?',
        id: '1'
    },
    {
        name: '怎么办理国际漫游服务?',
        id: '2'
    },
    {
        name: '如何办理宽带?',
        id: '3'
    }
]

const example_2 = [
    {
        name: '5G套餐推荐',
        id: '4'
    },
    {
        name: '如何办理语音通话和短信的基础套餐?',
        id: '5'
    },
    {
        name: '上不了网怎么办?',
        id: '6'
    }
]

const DeepSeekIndex: React.FC = () => {
    const [searchValue, setSearchValue] = useState<any>();
    const [disabled, setDisabled] = useState<boolean>(false);
    const [exampleFlag, setExampleFlag] = useState<string>('1')

    const [chatHistory, setChatHistory] = useState<any[]>([]);
    const [currentResponse, setCurrentResponse] = useState<string>('');

    const chatRef = useRef(null);

    useEffect(() => {
        const _time = getTime();
        const newHistory = [...chatHistory,
            {role: 'time', answer: _time},
            {
                role: 'example',
                answer: example_1
            }
        ];
        console.log('newHistory', newHistory)
        setChatHistory(newHistory);
    }, [])

    const refreshFun = () => {
        const _exampleFlag = _.cloneDeep(exampleFlag);
        const _example = _exampleFlag === '1' ? example_2 : example_1;
        const _chatHistory = _.cloneDeep(chatHistory);
        _chatHistory?.forEach((item: any) => {
            if (item?.role === 'example') {
                item.answer = _example
            }
        })
        setChatHistory(_chatHistory);
        const _newExampleFlag = _exampleFlag === '1' ? '2' : '1'
        setExampleFlag(_newExampleFlag);
    }

    const send = async (_searchValue?: string) => {
        if (disabled) return;
        setDisabled(true);
        console.log('searchValue', searchValue)
        const _value = _searchValue ? _searchValue : searchValue;
        const data = {
            "query": _value,
            "inputs": {},
            "response_mode": "streaming",
            "user": "11",
            "conversation_id": ""
        }
        const customHeaders = {
            'Authorization': 'Bearer app-XxOBqpQr6u4c43tIl6by4vpK'
        }

        const _time = getTime();
        const newHistory = [...chatHistory,
            {role: 'time', answer: _time},
            {role: 'user', answer: _value}
        ];
        setChatHistory(newHistory);
        setSearchValue('');
        let _currentResponse = '';

        try {
            const response = await fetch('http://36.34.99.80:8088/v1/chat-messages', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    // 这里可以添加自定义请求头
                    ...customHeaders
                },
                body: JSON.stringify({...data})
            });

            if (!response.ok) {
                throw new Error(`HTTP error! status: ${response.status}`);
            }

            const reader = response.body.getReader();
            const decoder = new TextDecoder();
            let buffer = '';

            while (true) {
                const {done, value} = await reader.read();
                if (done) break;
                buffer += decoder?.decode(value, {stream: true});
                const lines = buffer?.split('\n');
                buffer = lines.pop();
                lines.forEach(line => {
                    if (line.startsWith('data:')) {
                        const data = JSON.parse(line?.slice(5)?.trim());
                        setCurrentResponse(prev => prev + (data?.answer || ''));
                        _currentResponse = _currentResponse + (data?.answer || '');
                    }
                });
            }

            const updatedHistory = [...newHistory, {role: 'assistant', answer: _currentResponse}];
            setChatHistory(updatedHistory);
            setCurrentResponse('');

            setDisabled(false);


        } catch (error) {
            console.error('Stream error:', error);
        }

    }

    // 让会话一直展示最新
    useEffect(() => {
        if (chatRef.current) {
            chatRef.current.scrollTop = chatRef.current.scrollHeight;
        }
    }, [currentResponse]);


    useEffect(() => {
        console.log('chatHistory', chatHistory)
    }, [chatHistory])

    const handleKeyDown = (e) => {
        if (e.key === 'Enter' && !e.shiftKey) {
            e.preventDefault(); // 阻止默认换行
            send();
        }
    };

    return (
        <div className={'deep-seek'}>
            <img className={'deep-seek_bg'} src={bg} alt=""/>
            <div
                ref={chatRef}
                className={'deep-seek_content'}
            >
                <div className={'deep-seek_header'}>
                    <img src={banner} alt=""/>
                </div>
                {chatHistory?.map((msg, index) => (
                    <div key={index} className={`${msg.role === 'user' ? 'content-right' : msg.role === 'assistant' ? 'content-left' : 'content-center' }`}>
                        {
                            msg.role === 'time' ?
                                <div className={'current-time'}>{msg?.answer}</div>:
                            msg.role ===  'example'? <div className={'current-example'}>
                                <div className={'current-example_head'}>
                                    <p className={'current-example_head-name'}>你想了解什么呢</p>
                                    <img src={refresh} className={'refresh'} alt="" onClick={refreshFun}/>
                                </div>
                                {
                                    msg?.answer?.map((item:any) => {
                                        return <div
                                            className={'omit1 current-example_title'}
                                            key={item?.id}
                                            onClick={() => send(item?.name || '')}
                                        >{item?.name}</div>
                                    })
                                }
                                </div> :
                            msg.role === 'user' ? <p className={'current-ask'}>{msg?.answer}</p> :
                                <Markdown content={msg?.answer}/>
                        }

                    </div>
                ))}
                {currentResponse && (
                    <div className="content-left">
                        <Markdown content={currentResponse}/>
                    </div>
                )}
            </div>
            <div className={'deep-seek_footer'}>
                <Input
                    type="text"
                    value={searchValue}
                    className="deep-seek_footer-search"
                    placeholder="输入..."
                    onChange={(val: string) => setSearchValue(val)}
                    onKeyDown={handleKeyDown}
                />
                <Button className={`deep-seek_footer-send ${disabled ? 'disabled' : ''}`} color={'primary'} onClick={send}>发送</Button>
            </div>

        </div>
    );
};

export default DeepSeekIndex;