Преглед на файлове

分享页面和聊天功能优化

李富豪 преди 7 месеца
родител
ревизия
660b9508f2
променени са 4 файла, в които са добавени 720 реда и са изтрити 717 реда
  1. 22 4
      app/components/DeekSeekHome.tsx
  2. 423 420
      app/components/DeepSeekChat.tsx
  3. 120 143
      app/components/chat.tsx
  4. 155 150
      app/components/sidebar.tsx

+ 22 - 4
app/components/DeekSeekHome.tsx

@@ -1,6 +1,6 @@
 import * as React from 'react';
 import { useNavigate } from "react-router-dom";
-import { Chat } from './DeepSeekHomeChat';
+import { Chat } from './DeepSeekChat';
 import whiteLogo from "../icons/whiteLogo.png";
 import jkxz from "../icons/jkxz.png";
 import { useChatStore } from "../store";
@@ -31,13 +31,31 @@ const DeekSeek: React.FC = () => {
                 }
             },
             {
-                title: '员工小百科',
+                title: '上海建筑行业发展',
+                onClick: () => {
+                    navigate({
+                        pathname: '/knowledgeChat',
+                        search: '?showMenu=false&appId=1803686113584558081'
+                    })
+                }
             },
             {
-                title: '报批报建助手',
+                title: '数字监理师',
+                onClick: () => {
+                    navigate({
+                        pathname: '/knowledgeChat',
+                        search: '?showMenu=true&appId=1838073704727347200'
+                    })
+                }
             },
             {
-                title: '施工方案审查',
+                title: '知识管理平台操作手册问答',
+                onClick: () => {
+                    navigate({
+                        pathname: '/knowledgeChat',
+                        search: '?showMenu=true&appId=1838113155503525889'
+                    })
+                }
             },
             {
                 title: '更多',

Файловите разлики са ограничени, защото са твърде много
+ 423 - 420
app/components/DeepSeekChat.tsx


+ 120 - 143
app/components/chat.tsx

@@ -512,7 +512,9 @@ function useScrollToBottom(
 }
 
 export function ChatActions(props: {
+  isClickStop: boolean,
   sendStatus: boolean,
+  setSendStatus: (status: boolean) => void;
   setUserInput: (value: string) => void;
   doSubmit: (userInput: string) => void;
   uploadImage: () => void;
@@ -640,6 +642,13 @@ export function ChatActions(props: {
     }
   }, [chatStore.message]);
 
+  useEffect(() => {
+    if (props.isClickStop) {
+      props.setSendStatus(false);
+      setGuessList([]);
+    }
+  }, [props.isClickStop])
+
   return (
     <div className={styles["chat-input-actions"]}>
       {
@@ -939,6 +948,7 @@ function _Chat() {
   const chatStore = useChatStore();
   const session = chatStore.currentSession();
   const config = useAppConfig();
+  config.sendPreviewBubble = false;
   const fontSize = config.fontSize;
   const fontFamily = config.fontFamily;
 
@@ -1024,8 +1034,10 @@ function _Chat() {
       setAppList(list);
       let appValue = '';
       const search = location.search;
-      if (search.startsWith('?appId=')) {
-        const value = search.slice(7);
+      const params = new URLSearchParams(search);
+      const appId = params.get('appId');
+      if (appId) {
+        const value = appId;
         if (list.find((item: any) => item.value === value)) {
           appValue = value;
         } else {
@@ -1591,102 +1603,112 @@ function _Chat() {
 
   const stopAll = () => ChatControllerPool.stopAll();
 
+  const [isClickStop, setIsClickStop] = useState(false);
+
+  useEffect(() => {
+    if (!couldStop) {
+      setIsClickStop(false)
+    }
+  }, [couldStop])
+
   return (
     <div className={styles.chat} key={session.id}>
-      <div className="window-header" data-tauri-drag-region>
-        <div style={{ display: 'flex', alignItems: 'center' }}
-          className={`window-header-title ${styles["chat-body-title"]}`}>
-          <div>
-            {
-              isMobileScreen &&
-              <IconButton
-                style={{ padding: 0, marginRight: 20 }}
-                icon={<LeftIcon />}
-                text={Locale.NewChat.Return}
-                onClick={() => navigate('/knowledgeChat')}
-              />
-            }
-          </div>
-          <div>
-
-            <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
-              <Select
-                style={{ width: '100%', height: 38, marginRight: 5 }}
-                value={selectedFruit}
-                onChange={(value: "ONLINE" | "LOCAL") => {
-                  chatStore.clearSessions();
-                  chatStore.updateCurrentSession((values) => {
-                    values.appId = globalStore.selectedAppId;
-                  });
-                  navigate({ pathname: '/newChat' });
-                  setSelectedFruit(value);
-                  chatStore.setChatMode(value);
-                }}
-              >
-                {fruits.map(fruit => (
-                  <Select.Option key={fruit.id} value={fruit.id}>
-                    {fruit.name}
-                  </Select.Option>
-                ))}
-              </Select>
+      {
+        !location.search.includes('showMenu=false') &&
+        <div className="window-header" data-tauri-drag-region>
+          <div style={{ display: 'flex', alignItems: 'center' }}
+            className={`window-header-title ${styles["chat-body-title"]}`}>
+            <div>
               {
-                appList.length > 0 ?
-                  <Select
-                    style={{ width: '100%', height: 38, marginRight: 5 }}
-                    placeholder='请选择'
-                    options={appList}
-                    value={appValue}
-                    onChange={(value) => {
-                      setAppValue(value);
-                      globalStore.setSelectedAppId(value);
-                      chatStore.clearSessions();
-                      chatStore.updateCurrentSession((values) => {
-                        values.appId = value;
-                      });
-                      useChatStore.setState({
-                        message: {
-                          content: '',
-                          role: 'assistant',
-                        }
-                      });
-                      setSendStatus(false);
-                    }}
-                  />
-                  :
-                  null
+                isMobileScreen &&
+                <IconButton
+                  style={{ padding: 0, marginRight: 20 }}
+                  icon={<LeftIcon />}
+                  text={Locale.NewChat.Return}
+                  onClick={() => navigate('/knowledgeChat')}
+                />
               }
             </div>
+            <div>
+
+              <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
+                <Select
+                  style={{ width: '100%', height: 38, marginRight: 5 }}
+                  value={selectedFruit}
+                  onChange={(value: "ONLINE" | "LOCAL") => {
+                    chatStore.clearSessions();
+                    chatStore.updateCurrentSession((values) => {
+                      values.appId = globalStore.selectedAppId;
+                    });
+                    navigate({ pathname: '/newChat' });
+                    setSelectedFruit(value);
+                    chatStore.setChatMode(value);
+                  }}
+                >
+                  {fruits.map(fruit => (
+                    <Select.Option key={fruit.id} value={fruit.id}>
+                      {fruit.name}
+                    </Select.Option>
+                  ))}
+                </Select>
+                {
+                  appList.length > 0 ?
+                    <Select
+                      style={{ width: '100%', height: 38, marginRight: 5 }}
+                      placeholder='请选择'
+                      options={appList}
+                      value={appValue}
+                      onChange={(value) => {
+                        setAppValue(value);
+                        globalStore.setSelectedAppId(value);
+                        chatStore.clearSessions();
+                        chatStore.updateCurrentSession((values) => {
+                          values.appId = value;
+                        });
+                        useChatStore.setState({
+                          message: {
+                            content: '',
+                            role: 'assistant',
+                          }
+                        });
+                        setSendStatus(false);
+                      }}
+                    />
+                    :
+                    null
+                }
+              </div>
+            </div>
           </div>
-        </div>
 
-        <div className="window-actions">
-          <div className="window-action-button">
-            <Popover
-              trigger="click"
-              title="分享"
-              content={() => {
-                const url = `${window.location.origin}/#/knowledgeChat?appId=${appValue}`
-                return <div>
-                  <div style={{ marginBottom: 10 }}>
-                    {url}
+          <div className="window-actions">
+            <div className="window-action-button">
+              <Popover
+                trigger="click"
+                title="分享该应用"
+                content={() => {
+                  const url = `${window.location.origin}/#/knowledgeChat?showMenu=false&appId=${appValue}`
+                  return <div>
+                    <div style={{ marginBottom: 10 }}>
+                      {url}
+                    </div>
+                    <Button onClick={() => {
+                      navigator.clipboard.writeText(url);
+                      message.success('分享链接已复制到剪贴板');
+                    }}>
+                      复制
+                    </Button>
                   </div>
-                  <Button onClick={() => {
-                    navigator.clipboard.writeText(url);
-                    message.success('分享链接已复制到剪贴板');
-                  }}>
-                    复制
-                  </Button>
-                </div>
-              }
-              }>
-              <IconButton
-                icon={<ExportIcon />}
-                bordered
-                title={Locale.Chat.Actions.Export}
-              />
-            </Popover>
-          </div>
-          {/* {showMaxIcon && (
+                }
+                }>
+                <IconButton
+                  icon={<ExportIcon />}
+                  bordered
+                  title={Locale.Chat.Actions.Export}
+                />
+              </Popover>
+            </div>
+            {/* {showMaxIcon && (
             <div className="window-action-button">
               <IconButton
                 icon={config.tightBorder ? <MinIcon /> : <MaxIcon />}
@@ -1701,13 +1723,14 @@ function _Chat() {
               />
             </div>
           )} */}
-        </div>
-        {/* <PromptToast
+          </div>
+          {/* <PromptToast
           showToast={!hitBottom}
           showModal={showPromptModal}
           setShowModal={setShowPromptModal}
         /> */}
-      </div>
+        </div>
+      }
       <div
         className={styles["chat-body"]}
         ref={scrollRef}
@@ -1742,58 +1765,9 @@ function _Chat() {
                       <div className={styles["chat-message-container"]}>
                         <div className={styles["chat-message-header"]}>
                           <div className={styles["chat-message-avatar"]}>
-                            {/* <div className={styles["chat-message-edit"]}>
-                        <IconButton
-                          icon={<EditIcon />}
-                          aria={Locale.Chat.Actions.Edit}
-                          onClick={async () => {
-                            const newMessage = await showPrompt(
-                              Locale.Chat.Actions.Edit,
-                              getMessageTextContent(message),
-                              10,
-                            );
-                            let newContent: string | MultimodalContent[] =
-                              newMessage;
-                            const images = getMessageImages(message);
-                            if (images.length > 0) {
-                              newContent = [{ type: "text", text: newMessage }];
-                              for (let i = 0; i < images.length; i++) {
-                                newContent.push({
-                                  type: "image_url",
-                                  image_url: {
-                                    url: images[i],
-                                  },
-                                });
-                              }
-                            }
-                            chatStore.updateCurrentSession((session) => {
-                              const m = session.mask.context
-                                .concat(session.messages)
-                                .find((m) => m.id === message.id);
-                              if (m) {
-                                m.content = newContent;
-                              }
-                            });
-                          }}
-                        ></IconButton>
-                      </div> */}
                             {isUser ? (
                               // 在这里换头像
                               <div style={{ position: 'relative' }}>
-                                {/* <MaskAvatar */}
-                                {/*   avatar={session.mask.avatar} */}
-                                {/* /> */}
-                                {/* <div */}
-                                {/*   style={{ */}
-                                {/*     position: 'absolute', */}
-                                {/*     zIndex: 2, */}
-                                {/*     top: '50%', */}
-                                {/*     left: '50%', */}
-                                {/*     transform: ' translate(-50%, -50%)', */}
-                                {/*     fontSize: 14, */}
-                                {/*   }}> */}
-                                {/*   我 */}
-                                {/* </div> */}
                                 <div
                                   style={{
                                     position: 'absolute',
@@ -1867,7 +1841,7 @@ function _Chat() {
                         {
                           showTyping ?
                             <div className={styles["chat-message-status"]}>
-                              {isUser ? '正在输入…' : '正在查询文档…'}
+                              {isUser ? '' : '正在查询文档…'}
                             </div>
                             :
                             <div className={styles["chat-message-status"]}>
@@ -1994,7 +1968,9 @@ function _Chat() {
       <div className={styles["chat-input-panel"]}>
         {/* <PromptHints prompts={promptHints} onPromptSelect={onPromptSelect} /> */}
         <ChatActions
+          isClickStop={isClickStop}
           sendStatus={sendStatus}
+          setSendStatus={setSendStatus}
           setUserInput={setUserInput}
           doSubmit={doSubmit}
           uploadImage={uploadImage}
@@ -2072,6 +2048,7 @@ function _Chat() {
             onClick={() => {
               if (couldStop) {
                 stopAll();
+                setIsClickStop(true);
               } else {
                 doSubmit(userInput);
               }

+ 155 - 150
app/components/sidebar.tsx

@@ -356,170 +356,175 @@ export const SideBar = (props: { className?: string }) => {
   }, [chatStore.chatMode]);
 
   return (
-    <SideBarContainer
-      onDragStart={onDragStart}
-      shouldNarrow={shouldNarrow}
-      {...props}
-    >
+    <>
       {
-        getType() === 'deepSeek' &&
-        <div>
-          <img style={{ width: '100%' }} src={deepSeekSrc.src} />
-        </div>
-      }
-      <SideBarHeader
-        title={getType() === 'bigModel' ? '问答历史' : ''}
-        logo={getType() === 'bigModel' ? <img style={{ height: 40 }} src={faviconSrc.src} /> : ''}
-      >
-        <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 10 }}>
-          <Button
-            style={{ width: '48%' }}
-            onClick={() => {
-              navigate({ pathname: '/' });
-            }}
+        !location.search.includes('showMenu=false') &&
+        <SideBarContainer
+          onDragStart={onDragStart}
+          shouldNarrow={shouldNarrow}
+          {...props}
+        >
+          {
+            getType() === 'deepSeek' &&
+            <div>
+              <img style={{ width: '100%' }} src={deepSeekSrc.src} />
+            </div>
+          }
+          <SideBarHeader
+            title={getType() === 'bigModel' ? '问答历史' : ''}
+            logo={getType() === 'bigModel' ? <img style={{ height: 40 }} src={faviconSrc.src} /> : ''}
           >
-            回到首页
-          </Button>
-          <Button
-            style={{ width: '48%' }}
-            type="primary"
-            onClick={async () => {
-              chatStore.clearSessions();
-              chatStore.updateCurrentSession((value) => {
-                value.appId = globalStore.selectedAppId;
-              });
-              if (getType() === 'bigModel') {
-                navigate({ pathname: '/newChat' });
-              } else {
-                navigate({ pathname: '/newDeepseekChat' });
-              }
+            <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 10 }}>
+              <Button
+                style={{ width: '48%' }}
+                onClick={() => {
+                  navigate({ pathname: '/' });
+                }}
+              >
+                回到首页
+              </Button>
+              <Button
+                style={{ width: '48%' }}
+                type="primary"
+                onClick={async () => {
+                  chatStore.clearSessions();
+                  chatStore.updateCurrentSession((value) => {
+                    value.appId = globalStore.selectedAppId;
+                  });
+                  if (getType() === 'bigModel') {
+                    navigate({ pathname: '/newChat' });
+                  } else {
+                    navigate({ pathname: '/newDeepseekChat' });
+                  }
+                  if (getType() === 'bigModel') {
+                    if (chatStore.chatMode === 'LOCAL') {
+                      await fetchChatList(chatStore.chatMode);
+                    } else {
+                      await fetchChatList();
+                    }
+                  } else {
+                    await fetchChatList();
+                  }
+                }}
+              >
+                新建对话
+              </Button>
+            </div>
+          </SideBarHeader>
+          <Menu
+            style={{ border: 'none' }}
+            onClick={async ({ key }) => {
+              let url = ``;
               if (getType() === 'bigModel') {
                 if (chatStore.chatMode === 'LOCAL') {
-                  await fetchChatList(chatStore.chatMode);
+                  url = `/deepseek/api/dialog/detail/${key}`;
                 } else {
-                  await fetchChatList();
+                  url = `/bigmodel/api/dialog/detail/${key}`;
                 }
               } else {
-                await fetchChatList();
+                url = `/bigmodel/api/dialog/detail/${key}`;
               }
-            }}
-          >
-            新建对话
-          </Button>
-        </div>
-      </SideBarHeader>
-      <Menu
-        style={{ border: 'none' }}
-        onClick={async ({ key }) => {
-          let url = ``;
-          if (getType() === 'bigModel') {
-            if (chatStore.chatMode === 'LOCAL') {
-              url = `/deepseek/api/dialog/detail/${key}`;
-            } else {
-              url = `/bigmodel/api/dialog/detail/${key}`;
-            }
-          } else {
-            url = `/bigmodel/api/dialog/detail/${key}`;
-          }
-          const res = await api.get(url);
+              const res = await api.get(url);
 
-          // const document = {
-          //   id: "6e90c1c5-20ed-11f0-bcfc-22114d043191",
-          //   name: "ISHIGURO WEB EDI.pdf",
-          //   url: "http://xia0miduo.gicp.net:9000/papbtest///chatFiles/6e90c1c5-20ed-11f0-bcfc-22114d043191_ISHIGURO WEB EDI.pdf"
-          // }
+              // const document = {
+              //   id: "6e90c1c5-20ed-11f0-bcfc-22114d043191",
+              //   name: "ISHIGURO WEB EDI.pdf",
+              //   url: "http://xia0miduo.gicp.net:9000/papbtest///chatFiles/6e90c1c5-20ed-11f0-bcfc-22114d043191_ISHIGURO WEB EDI.pdf"
+              // }
 
-          const list = res.data.map(((item: any) => {
-            return {
-              id: item.did,
-              role: item.type,
-              date: item.create_time,
-              content: item.content,
-              document: item.document ? item.document : undefined,
-            }
-          }))
-          const session = {
-            appId: res.data.length ? res.data[0].appId : '',
-            dialogName: res.data.length ? res.data[0].dialog_name : '',
-            id: res.data.length ? res.data[0].id : '',
-            messages: list,
-          }
-          globalStore.setCurrentSession(session);
-          chatStore.clearSessions();
-          chatStore.updateCurrentSession((value) => {
-            value.appId = session.appId;
-            value.topic = session.dialogName;
-            value.id = session.id;
-            value.messages = list;
-          });
-          if (getType() === 'bigModel') {
-            navigate({ pathname: '/newChat' });
-          } else {
-            navigate({ pathname: '/newDeepseekChat' });
-          }
-        }}
-        mode="inline"
-        items={menuList}
-      />
-      <Modal
-        title="重命名"
-        open={modalOpen}
-        width={300}
-        maskClosable={false}
-        onOk={() => {
-          form.validateFields().then(async (values) => {
-            setModalOpen(false);
-            try {
-              if (getType() === 'bigModel') {
-                if (chatStore.chatMode === 'LOCAL') {
-                  await api.put(`/deepseek/api/dialog/update`, {
-                    id: values.dialogId,
-                    dialogName: values.dialogName
-                  });
-                  await fetchChatList(chatStore.chatMode);
-                } else {
-                  await api.put(`/bigmodel/api/dialog/update`, {
-                    id: values.dialogId,
-                    dialogName: values.dialogName
-                  });
-                  await fetchChatList();
+              const list = res.data.map(((item: any) => {
+                return {
+                  id: item.did,
+                  role: item.type,
+                  date: item.create_time,
+                  content: item.content,
+                  document: item.document ? item.document : undefined,
                 }
-              } else {
-                await api.put(`/bigmodel/api/dialog/update`, {
-                  id: values.dialogId,
-                  dialogName: values.dialogName
-                });
-                await fetchChatList();
+              }))
+              const session = {
+                appId: res.data.length ? res.data[0].appId : '',
+                dialogName: res.data.length ? res.data[0].dialog_name : '',
+                id: res.data.length ? res.data[0].id : '',
+                messages: list,
               }
+              globalStore.setCurrentSession(session);
+              chatStore.clearSessions();
               chatStore.updateCurrentSession((value) => {
-                value.topic = values.dialogName;
+                value.appId = session.appId;
+                value.topic = session.dialogName;
+                value.id = session.id;
+                value.messages = list;
               });
-            } catch (error) {
-              console.error(error);
-            }
-          }).catch((error) => {
-            console.error(error);
-          });
-        }}
-        onCancel={() => {
-          setModalOpen(false);
-        }}
-      >
-        <Form form={form} layout='inline'>
-          <FormItem name='dialogId' noStyle />
-          <FormItem
-            label='名称'
-            name='dialogName'
-            rules={[{ required: true, message: '名称不能为空', whitespace: true }]}
+              if (getType() === 'bigModel') {
+                navigate({ pathname: '/newChat' });
+              } else {
+                navigate({ pathname: '/newDeepseekChat' });
+              }
+            }}
+            mode="inline"
+            items={menuList}
+          />
+          <Modal
+            title="重命名"
+            open={modalOpen}
+            width={300}
+            maskClosable={false}
+            onOk={() => {
+              form.validateFields().then(async (values) => {
+                setModalOpen(false);
+                try {
+                  if (getType() === 'bigModel') {
+                    if (chatStore.chatMode === 'LOCAL') {
+                      await api.put(`/deepseek/api/dialog/update`, {
+                        id: values.dialogId,
+                        dialogName: values.dialogName
+                      });
+                      await fetchChatList(chatStore.chatMode);
+                    } else {
+                      await api.put(`/bigmodel/api/dialog/update`, {
+                        id: values.dialogId,
+                        dialogName: values.dialogName
+                      });
+                      await fetchChatList();
+                    }
+                  } else {
+                    await api.put(`/bigmodel/api/dialog/update`, {
+                      id: values.dialogId,
+                      dialogName: values.dialogName
+                    });
+                    await fetchChatList();
+                  }
+                  chatStore.updateCurrentSession((value) => {
+                    value.topic = values.dialogName;
+                  });
+                } catch (error) {
+                  console.error(error);
+                }
+              }).catch((error) => {
+                console.error(error);
+              });
+            }}
+            onCancel={() => {
+              setModalOpen(false);
+            }}
           >
-            <Input
-              style={{ width: 300 }}
-              placeholder='请输入'
-              maxLength={20}
-            />
-          </FormItem>
-        </Form>
-      </Modal>
-    </SideBarContainer>
+            <Form form={form} layout='inline'>
+              <FormItem name='dialogId' noStyle />
+              <FormItem
+                label='名称'
+                name='dialogName'
+                rules={[{ required: true, message: '名称不能为空', whitespace: true }]}
+              >
+                <Input
+                  style={{ width: 300 }}
+                  placeholder='请输入'
+                  maxLength={20}
+                />
+              </FormItem>
+            </Form>
+          </Modal>
+        </SideBarContainer>
+      }
+    </>
   );
 }

Някои файлове не бяха показани, защото твърде много файлове са промени