diff --git a/datacenter/.eslintrc.json b/datacenter/.eslintrc.json index bffb357a7..fb3c42820 100644 --- a/datacenter/.eslintrc.json +++ b/datacenter/.eslintrc.json @@ -1,3 +1,8 @@ { - "extends": "next/core-web-vitals" + "extends": "next/core-web-vitals", + "rules": { + "indent": ["warning", 2, { + "SwitchCase": 1 + }] + } } diff --git a/datacenter/app/agents/[agentId]/page.tsx b/datacenter/app/agents/[agentId]/page.tsx new file mode 100644 index 000000000..113bbb6a7 --- /dev/null +++ b/datacenter/app/agents/[agentId]/page.tsx @@ -0,0 +1,25 @@ +"use client" +import { useRequest } from 'ahooks'; +import { sendGetRequest } from '@/utils/request'; +import useAgentChat from '@/hooks/useAgentChat'; +import ChatBoxComp from '@/components/chatBox'; + +const AgentPage = (props) => { + const { data: historyList } = useRequest(async () => await sendGetRequest('/v1/chat/dialogue/messages/history', { + con_uid: props.params?.agentId + }), { + ready: !!props.params?.agentId + }); + + const { handleChatSubmit, history } = useAgentChat({ + queryAgentURL: `/v1/chat/completions`, + queryBody: {} + }); + + return ( +
+ +
+ ) +} +export default AgentPage; \ No newline at end of file diff --git a/datacenter/app/agents/page.tsx b/datacenter/app/agents/page.tsx index b23107334..9e1d252be 100644 --- a/datacenter/app/agents/page.tsx +++ b/datacenter/app/agents/page.tsx @@ -203,7 +203,7 @@ const Agents = () => { - + diff --git a/datacenter/app/datastores/documents/chunklist/page.tsx b/datacenter/app/datastores/documents/chunklist/page.tsx index 42c9da062..ca17030e9 100644 --- a/datacenter/app/datastores/documents/chunklist/page.tsx +++ b/datacenter/app/datastores/documents/chunklist/page.tsx @@ -32,7 +32,7 @@ const ChunkList = () => { }, []) return (
- +
diff --git a/datacenter/app/datastores/documents/page.tsx b/datacenter/app/datastores/documents/page.tsx index 23ee57bf3..f1612aaa1 100644 --- a/datacenter/app/datastores/documents/page.tsx +++ b/datacenter/app/datastores/documents/page.tsx @@ -10,11 +10,25 @@ import { Box, Stack, Input, + Chip, styled } from '@/lib/mui' import moment from 'moment' -import { message } from 'antd' +import { InboxOutlined } from '@ant-design/icons' +import type { UploadProps } from 'antd' +import { Upload, message } from 'antd' +const { Dragger } = Upload +const Item = styled(Sheet)(({ theme }) => ({ + width: '50%', + backgroundColor: + theme.palette.mode === 'dark' ? theme.palette.background.level1 : '#fff', + ...theme.typography.body2, + padding: theme.spacing(1), + textAlign: 'center', + borderRadius: 4, + color: theme.vars.palette.text.secondary +})) const stepsOfAddingDocument = [ 'Choose a Datasource type', 'Setup the Datasource' @@ -36,16 +50,6 @@ const documentTypeList = [ subTitle: 'It can be: PDF, CSV, JSON, Text, PowerPoint, Word, Excel' } ] -const Item = styled(Sheet)(({ theme }) => ({ - width: '50%', - backgroundColor: - theme.palette.mode === 'dark' ? theme.palette.background.level1 : '#fff', - ...theme.typography.body2, - padding: theme.spacing(1), - textAlign: 'center', - borderRadius: 4, - color: theme.vars.palette.text.secondary -})) const Documents = () => { const router = useRouter() @@ -53,9 +57,25 @@ const Documents = () => { const [isAddDocumentModalShow, setIsAddDocumentModalShow] = useState(false) const [activeStep, setActiveStep] = useState(0) + const [documentType, setDocumentType] = useState('') const [documents, setDocuments] = useState([]) const [webPageUrl, setWebPageUrl] = useState('') - const [documentName, setDocumentName] = useState('') + const [documentName, setDocumentName] = useState('') + const [originFileObj, setOriginFileObj] = useState(null) + const props: UploadProps = { + name: 'file', + multiple: false, + onChange(info) { + console.log(info) + if (info.fileList.length === 0) { + setOriginFileObj(null) + setDocumentName('') + return + } + setOriginFileObj(info.file.originFileObj) + setDocumentName(info.file.originFileObj?.name) + } + } useEffect(() => { async function fetchDocuments() { const res = await fetch( @@ -90,7 +110,7 @@ const Documents = () => { + Add Datasource -
Name
+
@@ -108,12 +128,30 @@ const Documents = () => { - +
Name{row.doc_type} {row.chunk_size} {moment(row.last_sync).format('YYYY-MM-DD HH:MM:SS')}{row.status} + + {row.status} + + { <>
- +
@@ -218,7 +245,7 @@ const Index = () => { sx={{ boxSizing: 'border-box', height: '80px', - padding: '12px', + padding: '12px', display: 'flex', flexDirection: 'column', justifyContent: 'space-between', @@ -228,12 +255,13 @@ const Index = () => { cursor: 'pointer' }} onClick={() => { - if (item.type === 'webPage') { - setActiveStep(2); - } + setDocumentType(item.type) + setActiveStep(2) }} > - {item.title} + + {item.title} + {item.subTitle} ))} @@ -246,44 +274,94 @@ const Index = () => { setDocumentName(e.target.value)} - sx={{ marginBottom: '20px'}} - /> - Web Page URL: - setWebPageUrl(e.target.value)} + sx={{ marginBottom: '20px' }} /> + {documentType === 'webPage' ? ( + <> + Web Page URL: + setWebPageUrl(e.target.value)} + /> + + ) : documentType === 'file' ? ( + <> + +

+ +

+

+ Select or Drop file +

+

+ PDF, PowerPoint, Excel, Word, Text, Markdown, +

+
+ + ) : ( + <> + )} + + + - )} - expandIconPosition="end" - items={[ - { - key: '1', - label: 'This panel can only be collapsed by clicking text', - children: ( - <> - -
- Temperature - { - setTemperatureNum(Number(e.target.value) * 10); - }} - slotProps={{ - input: { - min: 0, - max: 1, - step: 0.1, - }, - }} - /> -
- { - setTemperatureNum(value); - }} - /> -
- -
- Maximum output token size - { - setTokenSize(Number(e.target.value)); - }} - slotProps={{ - input: { - min: 0, - max: 1024, - step: 64, - }, - }} - /> -
- { - setTokenSize(value); - }} - /> -
- - ), - }, - ]} - /> - - - ({ - '--Tabs-gap': '0px', - borderRadius: 'unset', - boxShadow: 'sm', - overflow: 'auto', - WebkitBoxShadow: 'none' - })} + + +
+ +
+
{ + methods.handleSubmit(submit)(e); + }} > - - Documents Chat - SQL Generation & Diagnostics - Plugin Mode - - - - - - - - - - - - - - - - - - - - Best for professional developers building enterprise or data-rich - applications. - - - $15{' '} - - / dev / month - - - - - - The most advanced features for data-rich applications, as well as the - highest priority for support. - - - ({ - ...theme.variants.soft.danger, - color: 'danger.400', - verticalAlign: 'text-top', - textDecoration: 'line-through', - })} - > - $49 - - $37*{' '} - - / dev / month - - - - - - -
+ + + + } + {...methods.register('query')} + /> + + + ) } diff --git a/datacenter/components/chatBox.tsx b/datacenter/components/chatBox.tsx index 0a4ae2fa4..c7a6619cd 100644 --- a/datacenter/components/chatBox.tsx +++ b/datacenter/components/chatBox.tsx @@ -17,7 +17,7 @@ type Props = { messages: Message[]; onSubmit: (message: string) => Promise; messageTemplates?: string[]; - initialMessage?: string; + initialMessage?: Message; readOnly?: boolean; }; @@ -63,7 +63,7 @@ const ChatBoxComp = ({ React.useEffect(() => { setTimeout(() => { setFirstMsg( - initialMessage ? { from: 'agent', message: initialMessage } : undefined + initialMessage ? initialMessage : undefined ); }, 0); }, [initialMessage]); @@ -112,7 +112,7 @@ const ChatBoxComp = ({ whiteSpace: 'pre-wrap', }} > - {firstMsg?.message} + {firstMsg?.context} )} @@ -120,17 +120,17 @@ const ChatBoxComp = ({ ({ px: 2, 'ol, ul': { @@ -153,7 +153,7 @@ const ChatBoxComp = ({ })} > - {each.message} + {each.context} diff --git a/datacenter/components/leftSider.tsx b/datacenter/components/leftSider.tsx index 64cb9b2f3..3de584ddc 100644 --- a/datacenter/components/leftSider.tsx +++ b/datacenter/components/leftSider.tsx @@ -3,42 +3,26 @@ import React, { useMemo, useState } from 'react'; import { usePathname } from 'next/navigation'; import Link from 'next/link'; import Image from 'next/image'; -import { Box, List, ListItem, ListItemButton, ListItemDecorator, ListItemContent, Typography, Button, useColorScheme } from '@/lib/mui'; +import { Box, List, ListItem, ListItemButton, ListItemDecorator, ListItemContent, Typography, Button, useColorScheme, Alert } 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' - }] -}]; +import HomeIcon from '@mui/icons-material/Home'; +import MenuIcon from '@mui/icons-material/Menu'; +import AddIcon from '@mui/icons-material/Add'; +import { useQueryDialog } from '@/hooks/useQueryDialogue'; const LeftSider = () => { const pathname = usePathname(); const { mode, setMode } = useColorScheme(); const [chatSelect, setChatSelect] = useState(); + const { dialogueList } = useQueryDialog(); + const menus = useMemo(() => { return [{ label: 'Home', - icon: , + icon: , route: '/', active: pathname === '/', }, { @@ -63,153 +47,173 @@ const LeftSider = () => { }; return ( - - -
- - - DB-GPT - + <> + +
- -
+ + ) }; diff --git a/datacenter/hooks/useAgentChat.ts b/datacenter/hooks/useAgentChat.ts index 1122631e8..6f6276c91 100644 --- a/datacenter/hooks/useAgentChat.ts +++ b/datacenter/hooks/useAgentChat.ts @@ -21,22 +21,22 @@ import { }: Props) => { const [state, setState] = useStateReducer({ history: [{ - from: 'human', - message: 'hello', + role: 'human', + context: 'hello', }, { - from: 'agent', - message: 'Hello! How can I assist you today?', - }] as { from: 'human' | 'agent'; message: string; id?: string }[], + role: 'agent', + context: 'Hello! How can I assist you today?', + }] as { role: 'human' | 'agent'; context: string; id?: string }[], }); const { visitorId } = useVisitorId(); - const handleChatSubmit = async (message: string) => { - if (!message) { + const handleChatSubmit = async (context: string) => { + if (!context) { return; } - const history = [...state.history, { from: 'human', message }]; + const history = [...state.history, { role: 'human', context }]; const nextIndex = history.length; setState({ @@ -61,7 +61,7 @@ import { body: JSON.stringify({ ...queryBody, streaming: true, - query: message, + query: context, visitorId: visitorId, channel, }), @@ -112,8 +112,8 @@ import { history: [ ...history, { - from: 'agent', - message: event.data.replace('[ERROR]', ''), + role: 'agent', + context: event.data.replace('[ERROR]', ''), } as any, ], }); @@ -121,9 +121,9 @@ import { buffer += decodeURIComponent(event.data) as string; const h = [...history]; if (h?.[nextIndex]) { - h[nextIndex].message = `${buffer}`; + h[nextIndex].context = `${buffer}`; } else { - h.push({ from: 'agent', message: buffer }); + h.push({ role: 'agent', context: buffer }); } setState({ history: h as any, @@ -136,7 +136,7 @@ import { setState({ history: [ ...history, - { from: 'agent', message: answer || '请求出错' as string }, + { role: 'agent', context: answer || '请求出错' as string }, ] as any, }); // if (err instanceof ApiError) { diff --git a/datacenter/hooks/useQueryDialogue.ts b/datacenter/hooks/useQueryDialogue.ts new file mode 100644 index 000000000..93ca0225e --- /dev/null +++ b/datacenter/hooks/useQueryDialogue.ts @@ -0,0 +1,20 @@ +import { useRequest } from 'ahooks'; +import { sendGetRequest } from '@/utils/request'; + +export function useQueryDialog() { + const { + run: queryDialogueList, + data: dialogueList, + loading: loadingDialogList, + refresh: refreshDialogList, + } = useRequest(async () => await sendGetRequest('/v1/chat/dialogue/list'), { + manual: false, + }); + + return { + queryDialogueList, + dialogueList, + loadingDialogList, + refreshDialogList + }; +} \ No newline at end of file diff --git a/datacenter/package-lock.json b/datacenter/package-lock.json index e2262a9cd..682366559 100644 --- a/datacenter/package-lock.json +++ b/datacenter/package-lock.json @@ -24,6 +24,7 @@ "@types/node": "20.3.1", "@types/react": "18.2.14", "@types/react-dom": "18.2.6", + "ahooks": "^3.7.8", "antd": "^5.6.2", "autoprefixer": "10.4.14", "axios": "^1.3.4", @@ -31,6 +32,7 @@ "cuid": "^3.0.0", "eslint": "8.43.0", "eslint-config-next": "13.4.7", + "lodash": "^4.17.21", "moment": "^2.29.4", "next": "13.4.7", "next-auth": "^4.20.1", @@ -48,6 +50,7 @@ "zod": "^3.19.1" }, "devDependencies": { + "@types/lodash": "^4.14.195", "@types/nprogress": "^0.2.0" } }, @@ -2244,11 +2247,22 @@ "@types/unist": "*" } }, + "node_modules/@types/js-cookie": { + "version": "2.2.7", + "resolved": "https://registry.npmmirror.com/@types/js-cookie/-/js-cookie-2.2.7.tgz", + "integrity": "sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA==" + }, "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmmirror.com/@types/json5/-/json5-0.0.29.tgz", "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==" }, + "node_modules/@types/lodash": { + "version": "4.14.195", + "resolved": "https://registry.npmmirror.com/@types/lodash/-/lodash-4.14.195.tgz", + "integrity": "sha512-Hwx9EUgdwf2GLarOjQp5ZH8ZmblzcbTBC2wtQWNKARBSxM9ezRIAUpeDTgoQRAFB0+8CNWXVA9+MaSOzOF3nPg==", + "dev": true + }, "node_modules/@types/mdast": { "version": "3.0.11", "resolved": "https://registry.npmmirror.com/@types/mdast/-/mdast-3.0.11.tgz", @@ -2443,6 +2457,34 @@ "object-assign": "4.x" } }, + "node_modules/ahooks": { + "version": "3.7.8", + "resolved": "https://registry.npmmirror.com/ahooks/-/ahooks-3.7.8.tgz", + "integrity": "sha512-e/NMlQWoCjaUtncNFIZk3FG1ImSkV/JhScQSkTqnftakRwdfZWSw6zzoWSG9OMYqPNs2MguDYBUFFC6THelWXA==", + "dependencies": { + "@babel/runtime": "^7.21.0", + "@types/js-cookie": "^2.x.x", + "ahooks-v3-count": "^1.0.0", + "dayjs": "^1.9.1", + "intersection-observer": "^0.12.0", + "js-cookie": "^2.x.x", + "lodash": "^4.17.21", + "resize-observer-polyfill": "^1.5.1", + "screenfull": "^5.0.0", + "tslib": "^2.4.1" + }, + "engines": { + "node": ">=8.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/ahooks-v3-count": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/ahooks-v3-count/-/ahooks-v3-count-1.0.0.tgz", + "integrity": "sha512-V7uUvAwnimu6eh/PED4mCDjE7tokeZQLKlxg9lCTMPhN+NjsSbtdacByVlR1oluXQzD3MOw55wylDmQo4+S9ZQ==" + }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmmirror.com/ajv/-/ajv-6.12.6.tgz", @@ -4566,6 +4608,11 @@ "node": ">= 0.4" } }, + "node_modules/intersection-observer": { + "version": "0.12.2", + "resolved": "https://registry.npmmirror.com/intersection-observer/-/intersection-observer-0.12.2.tgz", + "integrity": "sha512-7m1vEcPCxXYI8HqnL8CKI6siDyD+eIWSwgB3DZA+ZTogxk9I4CDnj4wilt9x/+/QbHI4YG5YZNmC6458/e9Ktg==" + }, "node_modules/is-arguments": { "version": "1.1.1", "resolved": "https://registry.npmmirror.com/is-arguments/-/is-arguments-1.1.1.tgz", @@ -4856,6 +4903,11 @@ "resolved": "https://registry.npmmirror.com/jose/-/jose-4.14.4.tgz", "integrity": "sha512-j8GhLiKmUAh+dsFXlX1aJCbt5KMibuKb+d7j1JaOJG6s2UjX1PQlW+OKB/sD4a/5ZYF4RcmYmLSndOoU3Lt/3g==" }, + "node_modules/js-cookie": { + "version": "2.2.1", + "resolved": "https://registry.npmmirror.com/js-cookie/-/js-cookie-2.2.1.tgz", + "integrity": "sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==" + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz", @@ -5018,7 +5070,7 @@ }, "node_modules/lodash": { "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, "node_modules/lodash.debounce": { @@ -7308,6 +7360,14 @@ "loose-envify": "^1.1.0" } }, + "node_modules/screenfull": { + "version": "5.2.0", + "resolved": "https://registry.npmmirror.com/screenfull/-/screenfull-5.2.0.tgz", + "integrity": "sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/scroll-into-view-if-needed": { "version": "3.0.10", "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-3.0.10.tgz", @@ -9888,11 +9948,22 @@ "@types/unist": "*" } }, + "@types/js-cookie": { + "version": "2.2.7", + "resolved": "https://registry.npmmirror.com/@types/js-cookie/-/js-cookie-2.2.7.tgz", + "integrity": "sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA==" + }, "@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmmirror.com/@types/json5/-/json5-0.0.29.tgz", "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==" }, + "@types/lodash": { + "version": "4.14.195", + "resolved": "https://registry.npmmirror.com/@types/lodash/-/lodash-4.14.195.tgz", + "integrity": "sha512-Hwx9EUgdwf2GLarOjQp5ZH8ZmblzcbTBC2wtQWNKARBSxM9ezRIAUpeDTgoQRAFB0+8CNWXVA9+MaSOzOF3nPg==", + "dev": true + }, "@types/mdast": { "version": "3.0.11", "resolved": "https://registry.npmmirror.com/@types/mdast/-/mdast-3.0.11.tgz", @@ -10049,6 +10120,28 @@ "object-assign": "4.x" } }, + "ahooks": { + "version": "3.7.8", + "resolved": "https://registry.npmmirror.com/ahooks/-/ahooks-3.7.8.tgz", + "integrity": "sha512-e/NMlQWoCjaUtncNFIZk3FG1ImSkV/JhScQSkTqnftakRwdfZWSw6zzoWSG9OMYqPNs2MguDYBUFFC6THelWXA==", + "requires": { + "@babel/runtime": "^7.21.0", + "@types/js-cookie": "^2.x.x", + "ahooks-v3-count": "^1.0.0", + "dayjs": "^1.9.1", + "intersection-observer": "^0.12.0", + "js-cookie": "^2.x.x", + "lodash": "^4.17.21", + "resize-observer-polyfill": "^1.5.1", + "screenfull": "^5.0.0", + "tslib": "^2.4.1" + } + }, + "ahooks-v3-count": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/ahooks-v3-count/-/ahooks-v3-count-1.0.0.tgz", + "integrity": "sha512-V7uUvAwnimu6eh/PED4mCDjE7tokeZQLKlxg9lCTMPhN+NjsSbtdacByVlR1oluXQzD3MOw55wylDmQo4+S9ZQ==" + }, "ajv": { "version": "6.12.6", "resolved": "https://registry.npmmirror.com/ajv/-/ajv-6.12.6.tgz", @@ -11763,6 +11856,11 @@ "side-channel": "^1.0.4" } }, + "intersection-observer": { + "version": "0.12.2", + "resolved": "https://registry.npmmirror.com/intersection-observer/-/intersection-observer-0.12.2.tgz", + "integrity": "sha512-7m1vEcPCxXYI8HqnL8CKI6siDyD+eIWSwgB3DZA+ZTogxk9I4CDnj4wilt9x/+/QbHI4YG5YZNmC6458/e9Ktg==" + }, "is-arguments": { "version": "1.1.1", "resolved": "https://registry.npmmirror.com/is-arguments/-/is-arguments-1.1.1.tgz", @@ -11980,6 +12078,11 @@ "resolved": "https://registry.npmmirror.com/jose/-/jose-4.14.4.tgz", "integrity": "sha512-j8GhLiKmUAh+dsFXlX1aJCbt5KMibuKb+d7j1JaOJG6s2UjX1PQlW+OKB/sD4a/5ZYF4RcmYmLSndOoU3Lt/3g==" }, + "js-cookie": { + "version": "2.2.1", + "resolved": "https://registry.npmmirror.com/js-cookie/-/js-cookie-2.2.1.tgz", + "integrity": "sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==" + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz", @@ -12106,7 +12209,7 @@ }, "lodash": { "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, "lodash.debounce": { @@ -13904,6 +14007,11 @@ "loose-envify": "^1.1.0" } }, + "screenfull": { + "version": "5.2.0", + "resolved": "https://registry.npmmirror.com/screenfull/-/screenfull-5.2.0.tgz", + "integrity": "sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA==" + }, "scroll-into-view-if-needed": { "version": "3.0.10", "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-3.0.10.tgz", diff --git a/datacenter/package.json b/datacenter/package.json index c7c0843b4..c27347d4c 100644 --- a/datacenter/package.json +++ b/datacenter/package.json @@ -25,6 +25,7 @@ "@types/node": "20.3.1", "@types/react": "18.2.14", "@types/react-dom": "18.2.6", + "ahooks": "^3.7.8", "antd": "^5.6.2", "autoprefixer": "10.4.14", "axios": "^1.3.4", @@ -32,6 +33,7 @@ "cuid": "^3.0.0", "eslint": "8.43.0", "eslint-config-next": "13.4.7", + "lodash": "^4.17.21", "moment": "^2.29.4", "next": "13.4.7", "next-auth": "^4.20.1", @@ -49,6 +51,7 @@ "zod": "^3.19.1" }, "devDependencies": { + "@types/lodash": "^4.14.195", "@types/nprogress": "^0.2.0" } } diff --git a/datacenter/public/bg1.avif b/datacenter/public/bg1.avif new file mode 100644 index 000000000..a05ed83e3 Binary files /dev/null and b/datacenter/public/bg1.avif differ diff --git a/datacenter/public/bg2.png b/datacenter/public/bg2.png new file mode 100644 index 000000000..7c119cee8 Binary files /dev/null and b/datacenter/public/bg2.png differ diff --git a/datacenter/tailwind.config.js b/datacenter/tailwind.config.js index 5009e198b..c0d8ace57 100644 --- a/datacenter/tailwind.config.js +++ b/datacenter/tailwind.config.js @@ -14,5 +14,6 @@ module.exports = { } }, }, + darkMode: 'class', plugins: [], } diff --git a/datacenter/types/index.ts b/datacenter/types/index.ts index bb4b8128d..253f6f04e 100644 --- a/datacenter/types/index.ts +++ b/datacenter/types/index.ts @@ -1,7 +1,7 @@ import { NextApiRequest, NextPage } from 'next/types'; import { Session } from 'next-auth'; -export type Message = { from: 'human' | 'agent'; message: string; createdAt?: Date }; +export type Message = { role: 'human' | 'ai'; context: string; createdAt?: Date }; export type AppNextApiRequest = NextApiRequest & { session: Session; diff --git a/datacenter/utils/request.ts b/datacenter/utils/request.ts index 3413da66d..25e327ca6 100644 --- a/datacenter/utils/request.ts +++ b/datacenter/utils/request.ts @@ -1,4 +1,5 @@ import axios from 'axios'; +import { isPlainObject } from 'lodash'; axios.defaults.baseURL = 'http://30.183.153.244:5000'; @@ -9,6 +10,24 @@ axios.interceptors.response.use( err => Promise.reject(err) ); +const DEFAULT_HEADERS = { + 'content-type': 'application/json', +}; + +// body 字段 trim +const sanitizeBody = (obj: Record): string => { + // simple shallow copy to avoid changing original obj + if (!isPlainObject(obj)) return JSON.stringify(obj); + const resObj = { ...obj }; + for (const key in resObj) { + const val = resObj[key]; + if (typeof val === 'string') { + resObj[key] = val.trim(); + } + } + return JSON.stringify(resObj); +}; + export const sendGetRequest = (url: string, qs?: { [key: string]: any }) => { if (qs) { const str = Object.keys(qs) @@ -19,13 +38,15 @@ export const sendGetRequest = (url: string, qs?: { [key: string]: any }) => { url += `?${str}`; } } - axios.get(url, { - headers: { - "Content-Type": 'text/plain' - } - }).then(res => { - console.log(res, 'res'); - }).catch(err => { - console.log(err, 'err'); - }) + return axios.get(url, { + headers: DEFAULT_HEADERS + }).then(res => res).catch(err => Promise.reject(err)); } + +export const sendPostRequest = (url: string, body?: any) => { + const reqBody = sanitizeBody(body); + return axios.post(url, { + body: reqBody, + headers: DEFAULT_HEADERS + }).then(res => res).catch(err => Promise.reject(err)); +} \ No newline at end of file
Name