feat: 布局调整&添加首页

This commit is contained in:
changhuiping.chp 2023-06-27 11:15:11 +08:00
parent 10d6e23815
commit 7eb02a0dc2
6 changed files with 479 additions and 51 deletions

View File

@ -2,6 +2,10 @@
@tailwind components;
@tailwind utilities;
a {
color: #1677ff;
}
body {
margin: 0;
color: var(--joy-palette-text-primary, var(--joy-palette-neutral-800, #25252D));

View File

@ -1,6 +1,5 @@
"use client"
import './globals.css'
import Header from '@/components/header';
import LeftSider from '@/components/leftSider';
import { CssVarsProvider, ThemeProvider } from '@mui/joy/styles';
import { joyTheme } from './defaultTheme';
@ -16,10 +15,9 @@ export default function RootLayout({
<ThemeProvider theme={joyTheme}>
<CssVarsProvider theme={joyTheme} defaultMode="light">
<div className='min-h-screen flex flex-col'>
<Header />
<div className="flex flex-1 flex-row">
<LeftSider />
<div className='flex-1'>{children}</div>
<div className='flex-1 overflow-auto'>{children}</div>
</div>
</div>
</CssVarsProvider>

View File

@ -1,9 +1,270 @@
import Image from 'next/image'
"use client";
import ReactMarkdown from 'react-markdown';
import { Collapse } from 'antd';
import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown';
import { Box, Slider, Input, Tabs, TabList, Typography, TabPanel, Tab, RadioGroup, Radio, tabClasses, useColorScheme, radioClasses } from '@/lib/mui';
import { sendGetRequest } from '@/utils/request';
import { useEffect, useState } from 'react';
import ChatBoxComp from '@/components/chatBox';
import useAgentChat from '@/hooks/useAgentChat';
export default function Home() {
const [temperatureNum, setTemperatureNum] = useState(3);
const [tokenSize, setTokenSize] = useState(0);
const { mode, setMode } = useColorScheme();
const { handleChatSubmit, history } = useAgentChat({
queryAgentURL: `/api/agents/query`,
});
const handleGetD = () => {
sendGetRequest('/v1/chat/dialogue/list', {
})
}
console.log(mode, 'mode', radioClasses, 'radioClasses')
useEffect(() => {
handleGetD();
}, []);
return (
<div>
Hello GPT
<div className='p-6 w-full h-full text-sm flex flex-col gap-4'>
<ReactMarkdown linkTarget={'_blank'}>
[DB-GPT](https://github.com/csunny/DB-GPT) 是一个开源的以数据库为基础的GPT实验项目使用本地化的GPT大模型与您的数据和环境进行交互无数据泄露风险100% 私密100% 安全。
</ReactMarkdown>
<Box
sx={{
'& .ant-collapse': {
backgroundColor: 'var(--joy-palette-background-level1)',
color: 'var(--joy-palette-neutral-plainColor)'
},
'& .ant-collapse>.ant-collapse-item >.ant-collapse-header, & .ant-collapse .ant-collapse-content': {
color: 'var(--joy-palette-neutral-plainColor)'
},
'& .ant-collapse .ant-collapse-content>.ant-collapse-content-box': {
paddingTop: 0
}
}}
>
<Collapse
collapsible="header"
defaultActiveKey={['1']}
ghost
bordered
expandIcon={({ isActive }) => (
<div className={`text-2xl cursor-pointer ${isActive ? 'rotate-0' : 'rotate-90'}`}>
<ArrowDropDownIcon />
</div>
)}
expandIconPosition="end"
items={[
{
key: '1',
label: 'This panel can only be collapsed by clicking text',
children: (
<>
<Box
className="p-4 border"
sx={{
borderColor: 'var(--joy-palette-background-level2)',
}}
>
<div className='flex flex-row justify-between items-center'>
<span>Temperature</span>
<Input
size='sm'
type="number"
value={temperatureNum / 10}
onChange={(e) => {
console.log(Number(e.target.value) * 10, '===')
setTemperatureNum(Number(e.target.value) * 10);
}}
slotProps={{
input: {
min: 0,
max: 1,
step: 0.1,
},
}}
/>
</div>
<Slider
color="info"
value={temperatureNum}
max={10}
onChange={(e, value) => {
console.log(e, 'e', value, 'v')
setTemperatureNum(value);
}}
/>
</Box>
<Box
className="p-4 border border-t-0"
sx={{
borderColor: 'var(--joy-palette-background-level2)',
}}
>
<div className='flex flex-row justify-between items-center'>
<span>Maximum output token size</span>
<Input
size="sm"
type="number"
value={tokenSize}
onChange={(e) => {
setTokenSize(Number(e.target.value));
}}
slotProps={{
input: {
min: 0,
max: 1024,
step: 64,
},
}}
/>
</div>
<Slider
color="info"
value={tokenSize}
max={1024}
step={64}
onChange={(e, value) => {
console.log(e, 'e', value, 'v')
setTokenSize(value);
}}
/>
</Box>
</>
),
},
]}
/>
</Box>
<Box>
<Tabs
className='w-full'
aria-label="Pricing plan"
defaultValue={0}
sx={(theme) => ({
'--Tabs-gap': '0px',
borderRadius: 'unset',
boxShadow: 'sm',
overflow: 'auto',
WebkitBoxShadow: 'none'
})}
>
<TabList
sx={{
'--ListItem-radius': '0px',
borderRadius: 0,
bgcolor: 'background.body',
[`& .${tabClasses.root}`]: {
fontWeight: 'lg',
flex: 'unset',
position: 'relative',
[`&.${tabClasses.selected}`]: {
border: '1px solid var(--joy-palette-background-level2)',
borderTopLeftRadius: '8px',
borderTopRightRadius: '8px',
},
[`&.${tabClasses.selected}:before`]: {
content: '""',
display: 'block',
position: 'absolute',
bottom: -4,
width: '100%',
height: 6,
bgcolor: mode == 'dark' ? '#000' : 'var(--joy-palette-background-surface)',
},
[`&.${tabClasses.focusVisible}`]: {
outlineOffset: '-3px',
},
},
}}
>
<Tab sx={{ py: 1.5 }}>Documents Chat</Tab>
<Tab>SQL Generation & Diagnostics</Tab>
<Tab>Plugin Mode</Tab>
</TabList>
<TabPanel
value={0}
sx={{
p: 3,
border: '1px solid var(--joy-palette-background-level2)',
borderBottomLeftRadius: '8px',
borderBottomRightRadius: '8px',
}}
>
<RadioGroup
orientation="horizontal"
defaultValue="LLM native dialogue"
name="radio-buttons-group"
className='gap-3 p-3'
sx={{
backgroundColor: 'var(--joy-palette-background-level1)',
'& .MuiRadio-radio': {
borderColor: '#707070'
},
}}
>
<Box className="px-2 py-1 border rounded" sx={{ borderColor: 'var(--joy-palette-background-level2)' }}>
<Radio value="LLM native dialogue" label="LLM native dialogue" variant="outlined"
sx={{
borderColor: 'var(--joy-palette-neutral-outlinedHoverColor)',
}}
/>
</Box>
<Box className="px-2 py-1 border rounded" sx={{ borderColor: 'var(--joy-palette-background-level2)' }}>
<Radio value="Default documents" label="Default documents" variant="outlined" />
</Box>
<Box className="px-2 py-1 border rounded" sx={{ borderColor: 'var(--joy-palette-background-level2)' }}>
<Radio value="New documents" label="New documents" variant="outlined" />
</Box>
<Box className="px-2 py-1 border rounded" sx={{ borderColor: 'var(--joy-palette-background-level2)' }}>
<Radio value="Chat with url" label="Chat with url" variant="outlined" />
</Box>
</RadioGroup>
</TabPanel>
<TabPanel value={1} sx={{ p: 3 }}>
<Typography level="inherit">
Best for professional developers building enterprise or data-rich
applications.
</Typography>
<Typography textColor="primary.400" fontSize="xl3" fontWeight="xl" my={1}>
$15{' '}
<Typography fontSize="sm" textColor="text.secondary" fontWeight="md">
/ dev / month
</Typography>
</Typography>
</TabPanel>
<TabPanel value={2} sx={{ p: 3 }}>
<Typography level="inherit">
The most advanced features for data-rich applications, as well as the
highest priority for support.
</Typography>
<Typography textColor="primary.400" fontSize="xl3" fontWeight="xl" my={1}>
<Typography
fontSize="xl"
borderRadius="sm"
px={0.5}
mr={0.5}
sx={(theme) => ({
...theme.variants.soft.danger,
color: 'danger.400',
verticalAlign: 'text-top',
textDecoration: 'line-through',
})}
>
$49
</Typography>
$37*{' '}
<Typography fontSize="sm" textColor="text.secondary" fontWeight="md">
/ dev / month
</Typography>
</Typography>
</TabPanel>
</Tabs>
</Box>
<ChatBoxComp messages={history} onSubmit={handleChatSubmit}/>
</div>
)
}

View File

@ -76,7 +76,6 @@ const ChatBoxComp = ({
display: 'flex',
flex: 1,
flexBasis: '100%',
maxWidth: '700px',
width: '100%',
height: '100%',
maxHeight: '100%',

View File

@ -1,14 +1,40 @@
"use client";
import React, { useMemo } from 'react';
import React, { useMemo, useState } from 'react';
import { usePathname } from 'next/navigation';
import Link from 'next/link';
import { Box, List, ListItem, ListItemButton, ListItemDecorator, ListItemContent } from '@/lib/mui';
import Image from 'next/image';
import { Box, List, ListItem, ListItemButton, ListItemDecorator, ListItemContent, Typography, Button, useColorScheme } from '@/lib/mui';
import SmartToyRoundedIcon from '@mui/icons-material/SmartToyRounded'; // Icons import
import StorageRoundedIcon from '@mui/icons-material/StorageRounded';
import DarkModeIcon from '@mui/icons-material/DarkMode';
import WbSunnyIcon from '@mui/icons-material/WbSunny';
const mockHistory = [{
id: 1,
summary: "chat1",
history: [{
from: 'human',
message: 'Hello'
}, {
from: 'agent',
message: 'Hello! How can I assist you today?'
}]
}, {
id: 2,
summary: "天气",
history: [{
from: 'human',
message: '讲个笑话'
}, {
from: 'agent',
message: '当然这是一个经典的笑话xxx'
}]
}];
const LeftSider = () => {
const pathname = usePathname();
console.log(pathname, 'router')
const { mode, setMode } = useColorScheme();
const [chatSelect, setChatSelect] = useState();
const menus = useMemo(() => {
return [{
label: 'Agents',
@ -23,19 +49,111 @@ const LeftSider = () => {
}];
}, [pathname]);
const handleChangeTheme = () => {
if (mode === 'light') {
setMode('dark');
} else {
setMode('light');
}
};
return (
<Box
sx={[
{
p: 2,
sx={{
display: 'flex',
flexDirection: 'column',
borderRight: '1px solid',
borderColor: 'divider',
maxHeight: '100vh',
position: 'sticky',
left: '0px',
top: '0px',
overflow: 'hidden',
}}
>
<Box
sx={{
p: 2,
gap: 2,
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
}}
>
<div className='flex items-center justify-center gap-3'>
<Image
src="/databerry-logo-icon.png"
width="200"
height="200"
className='w-12'
alt="Databerry"
/>
<Typography component="h1" fontWeight="xl">
DB-GPT
</Typography>
</div>
</Box>
<Box
sx={{
px: 2
}}
>
<Button variant="outlined" color="primary" className='w-full'>+ </Button>
</Box>
<Box
sx={{
p: 2,
display: {
xs: 'none',
sm: 'initial',
},
maxHeight: '100%',
overflow: 'auto',
}}
>
<List size="sm" sx={{ '--ListItem-radius': '8px' }}>
<ListItem nested>
<List
size="sm"
aria-labelledby="nav-list-browse"
sx={{
'& .JoyListItemButton-root': { p: '8px' },
}}
>
{mockHistory.map((each, index) => (
<ListItem key={index}>
<ListItemButton
selected={chatSelect === each.id}
variant={chatSelect === each.id ? 'soft' : 'plain'}
onClick={() => {
setChatSelect(each.id);
}}
>
<ListItemContent>{each.summary}</ListItemContent>
</ListItemButton>
</ListItem>
))}
</List>
</ListItem>
</List>
</Box>
<div className='flex flex-col justify-between flex-1'>
<div></div>
<Box
sx={{
p: 2,
borderTop: '1px solid',
borderColor: 'divider',
display: {
xs: 'none',
sm: 'initial',
},
},
]}
position: 'sticky',
bottom: 0,
zIndex: 100,
background: 'var(--joy-palette-background-body)'
}}
>
<List size="sm" sx={{ '--ListItem-radius': '8px' }}>
<ListItem nested>
@ -50,13 +168,13 @@ const LeftSider = () => {
<Link key={each.route} href={each.route}>
<ListItem>
<ListItemButton
color="neutral"
selected={each.active}
variant={each.active ? 'soft' : 'plain'}
>
<ListItemDecorator
sx={{
color: each.active ? 'inherit' : 'neutral.500',
'--ListItemDecorator-size': '26px'
}}
>
{each.icon}
@ -68,8 +186,25 @@ const LeftSider = () => {
))}
</List>
</ListItem>
<ListItem>
<ListItemButton
onClick={handleChangeTheme}
>
<ListItemDecorator>
{mode === 'dark' ? (
<DarkModeIcon fontSize="small"/>
) : (
<WbSunnyIcon fontSize="small"/>
)}
</ListItemDecorator>
<ListItemContent>Theme</ListItemContent>
</ListItemButton>
</ListItem>
</List>
</Box>
</div>
</Box>
)
};

View File

@ -0,0 +1,31 @@
import axios from 'axios';
axios.defaults.baseURL = 'http://30.183.153.244:5000';
axios.defaults.timeout = 10000;
axios.interceptors.response.use(
response => response.data,
err => Promise.reject(err)
);
export const sendGetRequest = (url: string, qs?: { [key: string]: any }) => {
if (qs) {
const str = Object.keys(qs)
.filter(k => qs[k] !== undefined && qs[k] !== '')
.map(k => `${k}=${qs[k]}`)
.join('&');
if (str) {
url += `?${str}`;
}
}
axios.get(url, {
headers: {
"Content-Type": 'text/plain'
}
}).then(res => {
console.log(res, 'res');
}).catch(err => {
console.log(err, 'err');
})
}