|
|
@@ -3,7 +3,7 @@ import styles from "./home.module.scss";
|
|
|
import DragIcon from "../icons/drag.svg";
|
|
|
import faviconSrc from "../icons/favicon.png";
|
|
|
import deepSeekSrc from "../icons/deepSeek.png";
|
|
|
-import { EditOutlined } from '@ant-design/icons';
|
|
|
+import { MenuOutlined, PlusOutlined } from '@ant-design/icons';
|
|
|
import { useAppConfig, useChatStore, useGlobalStore } from "../store";
|
|
|
import {
|
|
|
DEFAULT_SIDEBAR_WIDTH,
|
|
|
@@ -13,11 +13,7 @@ import {
|
|
|
} from "../constant";
|
|
|
import { useLocation, useNavigate } from "react-router-dom";
|
|
|
import { isIOS, useMobileScreen } from "../utils";
|
|
|
-import api from "@/app/api/api";
|
|
|
-import { Button, Dropdown, Form, Input, Menu, Modal } from "antd";
|
|
|
-import { downloadFile } from "../utils/index";
|
|
|
-
|
|
|
-const FormItem = Form.Item;
|
|
|
+import { Button } from "antd";
|
|
|
|
|
|
export function useHotKey() {
|
|
|
const chatStore = useChatStore();
|
|
|
@@ -102,7 +98,7 @@ export function useDragSideBar() {
|
|
|
const barWidth = shouldNarrow
|
|
|
? NARROW_SIDEBAR_WIDTH
|
|
|
: limit(config.sidebarWidth ?? DEFAULT_SIDEBAR_WIDTH);
|
|
|
- const sideBarWidth = isMobileScreen ? "100vw" : `${barWidth}px`;
|
|
|
+ const sideBarWidth = isMobileScreen ? "60vw" : `${barWidth}px`;
|
|
|
document.documentElement.style.setProperty("--sidebar-width", sideBarWidth);
|
|
|
}, [config.sidebarWidth, isMobileScreen, shouldNarrow]);
|
|
|
|
|
|
@@ -194,17 +190,13 @@ export function SideBarTail(props: {
|
|
|
}
|
|
|
|
|
|
export const SideBar = (props: { className?: string }) => {
|
|
|
- // useHotKey();
|
|
|
const { onDragStart, shouldNarrow } = useDragSideBar();
|
|
|
- const [showPluginSelector, setShowPluginSelector] = useState(false);
|
|
|
const navigate = useNavigate();
|
|
|
const location = useLocation();
|
|
|
const chatStore = useChatStore();
|
|
|
const globalStore = useGlobalStore();
|
|
|
+ const isMobileScreen = useMobileScreen();
|
|
|
|
|
|
- const [menuList, setMenuList] = useState([])
|
|
|
- const [modalOpen, setModalOpen] = useState(false)
|
|
|
- const [form] = Form.useForm();
|
|
|
const getType = (): 'bigModel' | 'deepSeek' => {
|
|
|
if (['/knowledgeChat', '/newChat'].includes(location.pathname)) {
|
|
|
return 'bigModel';
|
|
|
@@ -215,150 +207,22 @@ export const SideBar = (props: { className?: string }) => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // 获取聊天列表
|
|
|
- const fetchChatList = async (chatMode?: 'ONLINE' | 'LOCAL') => {
|
|
|
- try {
|
|
|
- let url = '';
|
|
|
- if (getType() === 'bigModel') {
|
|
|
- const appId = globalStore.selectedAppId;
|
|
|
- if (appId) {
|
|
|
- if (chatMode === 'LOCAL') {
|
|
|
- url = `/deepseek/api/dialog/list/${appId}`;
|
|
|
- } else {
|
|
|
- url = `/bigmodel/api/dialog/list/${appId}`;
|
|
|
- }
|
|
|
- }
|
|
|
- } else {
|
|
|
- const appId = '1881269958412521255';
|
|
|
- url = `/bigmodel/api/dialog/list/${appId}`;
|
|
|
- }
|
|
|
-
|
|
|
- const res = await api.get(url);
|
|
|
- const list = res.data.map((item: any) => {
|
|
|
- return {
|
|
|
- ...item,
|
|
|
- children: item.children.map((child: any) => {
|
|
|
- const items = [
|
|
|
- {
|
|
|
- key: '1',
|
|
|
- label: (
|
|
|
- <a onClick={() => {
|
|
|
- setModalOpen(true);
|
|
|
- form.setFieldsValue({
|
|
|
- dialogId: child.key,
|
|
|
- dialogName: child.label
|
|
|
- });
|
|
|
- }}>
|
|
|
- 重命名
|
|
|
- </a>
|
|
|
- ),
|
|
|
- },
|
|
|
- {
|
|
|
- key: '2',
|
|
|
- label: (
|
|
|
- <a onClick={async () => {
|
|
|
- try {
|
|
|
- let blob = null;
|
|
|
- if (getType() === 'bigModel') {
|
|
|
- if (chatMode === 'LOCAL') {
|
|
|
- blob = await api.post(`/deepseek/api/dialog/export/${child.key}`, {}, { responseType: 'blob' });
|
|
|
- } else {
|
|
|
- blob = await api.post(`/bigmodel/api/dialog/export/${child.key}`, {}, { responseType: 'blob' });
|
|
|
- }
|
|
|
- } else {
|
|
|
- blob = await api.post(`/bigmodel/api/dialog/export/${child.key}`, {}, { responseType: 'blob' });
|
|
|
- }
|
|
|
- const fileName = `${child.label}.xlsx`;
|
|
|
- downloadFile(blob, fileName);
|
|
|
- } catch (error) {
|
|
|
- console.error(error);
|
|
|
- }
|
|
|
- }}>
|
|
|
- 导出
|
|
|
- </a>
|
|
|
- ),
|
|
|
- },
|
|
|
- {
|
|
|
- key: '3',
|
|
|
- label: (
|
|
|
- <a onClick={async () => {
|
|
|
- try {
|
|
|
- if (getType() === 'bigModel') {
|
|
|
- if (chatMode === 'LOCAL') {
|
|
|
- await api.delete(`/deepseek/api/dialog/del/${child.key}`);
|
|
|
- await fetchChatList(chatMode);
|
|
|
- } else {
|
|
|
- await api.delete(`/bigmodel/api/dialog/del/${child.key}`);
|
|
|
- await fetchChatList();
|
|
|
- }
|
|
|
- } else {
|
|
|
- await api.delete(`/bigmodel/api/dialog/del/${child.key}`);
|
|
|
- await fetchChatList();
|
|
|
- }
|
|
|
- chatStore.clearSessions();
|
|
|
- useChatStore.setState({
|
|
|
- message: {
|
|
|
- content: '',
|
|
|
- role: 'assistant',
|
|
|
- }
|
|
|
- });
|
|
|
- } catch (error) {
|
|
|
- console.error(error);
|
|
|
- }
|
|
|
- }}>
|
|
|
- 删除
|
|
|
- </a>
|
|
|
- ),
|
|
|
- },
|
|
|
- ];
|
|
|
- return {
|
|
|
- ...child,
|
|
|
- label: <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
|
|
- <div style={{ flex: 1, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', marginRight: 10 }}>
|
|
|
- {child.label}
|
|
|
- </div>
|
|
|
- <div style={{ width: 20 }}>
|
|
|
- <Dropdown menu={{ items }} trigger={['click']} placement="bottomRight">
|
|
|
- <EditOutlined onClick={(e) => e.stopPropagation()} />
|
|
|
- </Dropdown>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- }
|
|
|
- })
|
|
|
- }
|
|
|
- })
|
|
|
- setMenuList(list);
|
|
|
- } catch (error) {
|
|
|
- console.error(error)
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- useEffect(() => {
|
|
|
- if (getType() === 'bigModel') {
|
|
|
- if (globalStore.selectedAppId) {
|
|
|
- fetchChatList(chatStore.chatMode);
|
|
|
- }
|
|
|
- }
|
|
|
- }, [globalStore.selectedAppId]);
|
|
|
-
|
|
|
- useEffect(() => {
|
|
|
- chatStore.clearSessions();
|
|
|
- useChatStore.setState({
|
|
|
- message: {
|
|
|
- content: '',
|
|
|
- role: 'assistant',
|
|
|
- }
|
|
|
- });
|
|
|
- }, []);
|
|
|
-
|
|
|
- useEffect(() => {
|
|
|
- fetchChatList(chatStore.chatMode);
|
|
|
- }, [chatStore.chatMode]);
|
|
|
+ const closeSidebar = () => {
|
|
|
+ globalStore.setShowMenu(false);
|
|
|
+ };
|
|
|
|
|
|
return (
|
|
|
<>
|
|
|
{
|
|
|
- !location.search.includes('showMenu=false') &&
|
|
|
+ isMobileScreen && globalStore.showMenu && (
|
|
|
+ <div
|
|
|
+ className={styles["sidebar-overlay"]}
|
|
|
+ onClick={closeSidebar}
|
|
|
+ />
|
|
|
+ )
|
|
|
+ }
|
|
|
+ {
|
|
|
+ (location.search.includes('showMenu=false') ? globalStore.showMenu : true) &&
|
|
|
<SideBarContainer
|
|
|
onDragStart={onDragStart}
|
|
|
shouldNarrow={shouldNarrow}
|
|
|
@@ -371,153 +235,40 @@ export const SideBar = (props: { className?: string }) => {
|
|
|
</div>
|
|
|
}
|
|
|
<SideBarHeader
|
|
|
- title={getType() === 'bigModel' ? '问答历史' : ''}
|
|
|
- logo={getType() === 'bigModel' ? <img style={{ height: 40 }} src={faviconSrc.src} /> : ''}
|
|
|
+ title={getType() === 'bigModel' ?
|
|
|
+ <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
|
|
|
+ <img style={{ height: 32 }} src={faviconSrc.src} />
|
|
|
+ <span>建科•小智</span>
|
|
|
+ </div>
|
|
|
+ :
|
|
|
+ ''
|
|
|
+ }
|
|
|
+ logo={getType() === 'bigModel' ? null : ''}
|
|
|
>
|
|
|
- <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 10 }}>
|
|
|
+ <div style={{ marginTop: 20 }}>
|
|
|
<Button
|
|
|
- style={{ width: '48%' }}
|
|
|
- onClick={() => {
|
|
|
- navigate({ pathname: '/' });
|
|
|
- }}
|
|
|
- >
|
|
|
- 回到首页
|
|
|
- </Button>
|
|
|
- <Button
|
|
|
- style={{ width: '48%' }}
|
|
|
+ style={{ width: '100%' }}
|
|
|
type="primary"
|
|
|
+ icon={<PlusOutlined />}
|
|
|
onClick={async () => {
|
|
|
chatStore.clearSessions();
|
|
|
chatStore.updateCurrentSession((value) => {
|
|
|
value.appId = globalStore.selectedAppId;
|
|
|
});
|
|
|
+ if (isMobileScreen) {
|
|
|
+ closeSidebar();
|
|
|
+ }
|
|
|
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') {
|
|
|
- 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 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,
|
|
|
- sliceInfo: item.sliceInfo ? item.sliceInfo : undefined,
|
|
|
- networkInfo: item.networkInfo ? item.networkInfo : 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();
|
|
|
- }
|
|
|
- } 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);
|
|
|
- }}
|
|
|
- >
|
|
|
- <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>
|
|
|
}
|
|
|
</>
|