npm package: @lmecosystem/chat-webkit
Description: Provide some common components for chat
Latest version: 0.0.1

# chat-webkit 接入文档

提供会话相关的前端组件能力，组件列表：
* **ChatBox**: SSE实时对话流
* **ChatManagement**: 会话管理

## 1. 使用说明

在React工程中引入组件

```
npm i -S chat-webkit
```

环境要求
```
React >= 18.0.0
```

## 2. ChatBox
SSE实时对话流组件，提供对话交互UI、对话状态扭转和样式高度自定义

### 2.1 参数说明

#### 2.1.1 组件入参说明

| **参数** | **说明** | **是否必需** | **类型** | **默认值** | **版本** |
| --- | --- | --- | --- | --- | --- |
| propsSessionList | 传入的历史对话记录 | 是 | SseMesage[] |  |  |
| url | sse 连接地址（唯一） | 是 | string |  |  |
| eventName | sse 返回数据时，监听事件名称 | 否 | string |  |  |
| style | 对话框样式自定义 | 否 | React.CSSProperties |  |  |
| sseMaxWaitTime | SSE 连接超时时间 | 否 | number |  |  |
| sseNoMessageWaitTime | 无消息，超时会话等待 | 否 | number |  |  |
| sseActiveWaitTime | 会话中（已收到消息），超时提示等待 | 否 | number |  |  |
| sseActiveCloseTime | 会话中（已收到消息），超时主动关闭 | 否 | number |  |  |
| token | 头部鉴权信息 | 否 | string |  |  |
| requestMessageContainerStyle | 提问对话框样式自定义 | 否 | React.CSSProperties |  |  |
| responseMessageContainerStyle | 回答对话框样式自定义 | 否 | React.CSSProperties |  |  |
| isShowStopGenerateButton | 是否显示停止生成按钮 | 否 | boolean | true |  |
| stopGenerateButtonStyle | 停止生成按钮 样式自定义 | 否 | React.CSSProperties |  |  |
| stopGenerateWords | 停止生成文字配置  | 否 | string | 停止生成 |  |
| isShowRegenerateButton | 当会话失败时， 是否显示重新生成 按钮  | 否 | boolean | true |  |
| reGenerateComponent | 重新生成组件 ，若不传则用默认 | 否 | JSX.Element |  |  |
| tooLongErrorComponent | 超长提示 暴露组件,若不传则用默认 | 否 | JSX.Element |  |  |
| modelCloseStyle | 模型关闭样式自定义 | 否 | React.CSSProperties |  |  |

#### 2.1.2 SseMesage说明

| **参数** | **说明** | **是否必需** | **类型** | **默认值** | **版本** |
| --- | --- | --- | --- | --- | --- |
| id | 聊天id（唯一） | 是 | number |  |  |
| status | 对话状态，0：对话停止状态 2:对话进行中 | 是 | number |  |  |
| message | 对话回复信息 | 是 | string |  |  |
| question | 对话问题A | 是 | string |  |  |

#### 2.1.3 SSE返回的数据格式说明

| **参数** | **说明** | **是否必需** | **类型** | **默认值** | **版本** |
| --- | --- | --- | --- | --- | --- |
| code | 状态码 | 是 | AllStatus |  |  |
| data | 数据 | 是 | Data |  |  |

#### 2.1.4  AllStatus说明

| **枚举值** | **说明** | **版本** |
| --- | --- | --- |
| 3 | 发起请求5s 内，无消息 |  |
| 4 | 发起请求5s 后，无消息  |  |
| 1 | 接收到event stream，流式输出中 |  |
| -1 | 接收出错 |  |
| 0 | 接收完成 |  |
| -20003 | 会话超长 |  |
| -20008 | 模型关闭 |  |
| -20015 | 会话中，后端超时 |  |

#### 2.1.5 Data说明

| **参数** | **说明** | **是否必需** | **类型** | **默认值** | **版本** |
| --- | --- | --- | --- | --- | --- |
| **context** |  | 是 | string |  |  |
| **id** |  | 是 | number |  |  |
| **request** |  | 是 | string |  |  |
| **response** |  | 是 | string |  |  |

### 2.2 使用demo

```JSX
import React,{  useRef } from 'react';

import styles from './App.module.less';

import ChatWebkit from 'chat-webkit';

const TooLongErrorComponent = ()=>{
  const a = ()=>{
    alert("ddd")

  }

  return (
    <div onClick={a}>
      tooo lll
    </div>
  )
}

const App: React.FC = () => {
  const ref = useRef<any>();
  const ref1 = useRef<any>();
  const ref2 = useRef<any>();
  const ref3 = useRef<any>();

  const sessionList = [
    {
      id: 140385,
      status: 0,
      message: '你好！我是聊天机器人，很高兴能够帮助你。你有什么需要帮助的事情吗？',
      question: 'ni hao ',
    },
    {
      id: 140386,
      status: 0,
      message: '你好！我是聊天机器人，很高兴能够帮助你。你有什么需要帮助的事情吗？',
      question: 'ni hao ',
    },
  ];

  const startSse = () => {
    ref.current.startSse('test');
    ref1.current.startSse('test');
    ref2.current.startSse('test');
    ref3.current.startSse('test');
  };

  const stopSse = () => {
    ref.current.stopSse();
    ref1.current.stopSse();
    ref2.current.stopSse();
    ref3.current.stopSse();
  }

  const reGenerate = () => {
    ref.current.reGenerate();
    ref1.current.reGenerate();
    ref2.current.reGenerate();
    ref3.current.reGenerate();
  };

  const getSseStatus = () => {
    console.log(ref.current.getStatus());
    console.log(ref1.current.getStatus());
    console.log(ref2.current.getStatus());
    console.log(ref3.current.getStatus());
  };

  return (
    <>
      <div className={styles.chatContainer}>
        <ChatWebkit.ChatBox
          tooLongErrorComponent={TooLongErrorComponent()}
          eventName=''
          propsSessionList={sessionList}
          url={'/chat/generate?turn_id=125612&username=gtl'}
          ref={ref}
          requestMessageContainerStyle={{backgroundColor:'red'}}
          responseMessageContainerStyle={{backgroundColor:'blue'}}
        />
        <ChatWebkit.ChatBox
          propsSessionList={sessionList}
          url={'/puyu/chats/1951/records/generate'}
          ref={ref1}
        />
        <ChatWebkit.ChatBox
          propsSessionList={sessionList}
          url={'/puyu/chats/1952/records/generate'}
          ref={ref2}
        />
        <ChatWebkit.ChatBox
          propsSessionList={sessionList}
          url={'/puyu/chats/1953/records/generate'}
          ref={ref3}
        />
      </div>
      <button onClick={startSse}>开始会话</button>
      <button onClick={stopSse}>停止会话</button>
      <button onClick={reGenerate}>重试</button>
      <button onClick={getSseStatus}>获取状态</button>
    </>
  );
};

export default App;
```

## 3. ChatManagement

会话管理组件，提供会话管理的自定义能力和样式

### 3.1 参数说明

#### 3.1.1 组件入参说明

| **参数** | **说明** | **是否必需** | **类型** | **默认值** | **版本** |
| --- | --- | --- | --- | --- | --- |
| list | 会话列表 | 是 | IChatItem[] | [] |  |
| selectedChatId | 选中的会话 | 是 | string | '' |  |
| ellipsis | 会话名称省略的最大行数 | 否 | Int  | 2 |  |
| addCallback | 新建会话回调，需更新list | 是 | () => void | - |  |
| deleteCallback | 删除会话回调，需更新list | 是 | (id:string) => void | - |  |
| selectCallback | 选中会话回调，需处理对话流的切换 | 是 | (id:string) => void | - |  |
| emptyRender | 空列表状态下的自定义渲染，默认不渲染 | 否 | ReactNode | - |  |
| itemRender | 单条会话的自定义渲染 | 否 | ReactNode | - |  |
| addRender | 新建会话的自定义渲染 | 否 | ReactNode | - |  |
| optionRender | 会话操作的自定义渲染 | 否 | ReactNode | - |  |

#### 3.1.2 IChatItem说明

| **参数** | **说明** | **是否必需** | **类型** | **默认值** | **版本** |
| --- | --- | --- | --- | --- | --- |
| id | 唯一标识id | 是 | string | - |  |
| name | 名称 | 是 | string | - |  |

### 3.2 使用demo

```JSX
import style from './App.module.less';
import ChatWebkit, {IChatItem} from 'chat-webkit'
import { useState } from 'react';

function App() {
    const [curChatId, setCurChatId] = useState<string>('')
    const [chatList, setChatList] = useState<IChatItem[]>([{
        id: '1',
        name: '开始会话后，这里就会显示第一句话，如果太长',
    },{
        id: '2',
        name: '创建后的默认名称叫做“新会话”',
    },{
        id: '3',
        name: '最多显示两行'
    }])

    const addChat = () => {
        const newItem = {
            id: Date.now().toString(),
            name: '新会话'
        }
        const newList = chatList.slice()
        newList.unshift(newItem)
        setChatList(newList)
        setCurChatId(newItem.id)
    }

    const deleteChat = (id: string) => {
        const newList = chatList.slice()
        const index = chatList.findIndex(x => x.id === id)
        if (index >= 0) {
            newList.splice(index, 1)
            setChatList(newList)
        }
    }

    const selectChat = (id:string) => {
        setCurChatId(id)
    }

    return (
        <div className={style.app} id="app">
            <div className={style.content}>
                <div className={style.title}>ChatZoo</div>
                <ChatWebkit.ChatManagement  
                    list={chatList} 
                    selectedChatId={curChatId}
                    addCallback={addChat} 
                    deleteCallback={deleteChat} 
                    selectCallback={selectChat} 
                />
            </div>
            <div className={style.right}>
                {curChatId}
            </div>
        </div>
    );
}

export default App;
```