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/defaultTheme.ts b/datacenter/app/defaultTheme.ts index 8dad1768e..a89e57658 100644 --- a/datacenter/app/defaultTheme.ts +++ b/datacenter/app/defaultTheme.ts @@ -10,7 +10,7 @@ export const joyTheme = extendTheme({ ...colors.purple, }, neutral: { - plainColor: '#25252D', + plainColor: '#4d4d4d', plainHoverColor: '#131318', plainHoverBg: '#EBEBEF', plainActiveBg: '#D8D8DF', @@ -42,7 +42,7 @@ export const joyTheme = extendTheme({ primary: '#EBEBEF' }, background: { - body: '#09090D', + body: '#0f172a', surface: '#1e293b40' } }, diff --git a/datacenter/app/globals.css b/datacenter/app/globals.css index b7240b7bf..04a5d0afa 100644 --- a/datacenter/app/globals.css +++ b/datacenter/app/globals.css @@ -2,9 +2,6 @@ @tailwind components; @tailwind utilities; -a { - color: #1677ff; -} body { margin: 0; diff --git a/datacenter/app/layout.tsx b/datacenter/app/layout.tsx index f5babbc38..6cfbbdf7c 100644 --- a/datacenter/app/layout.tsx +++ b/datacenter/app/layout.tsx @@ -10,20 +10,21 @@ export default function RootLayout({ children, }: { children: React.ReactNode -}) { - +}) { return ( - - + + -
-
- -
{children}
+
+
+ +
+ {children} +
+
-
diff --git a/datacenter/app/page.tsx b/datacenter/app/page.tsx index d6f6dab28..9883b43a2 100644 --- a/datacenter/app/page.tsx +++ b/datacenter/app/page.tsx @@ -1,267 +1,98 @@ "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'; +import { useState } from 'react'; +import { Button, Input, useColorScheme } from '@/lib/mui'; +import IconButton from '@mui/joy/IconButton'; +import SendRoundedIcon from '@mui/icons-material/SendRounded'; +import { zodResolver } from '@hookform/resolvers/zod'; +import { useForm } from 'react-hook-form'; +import { z } from 'zod'; +import { sendPostRequest } from '@/utils/request'; +import { useRouter } from 'next/navigation'; +import { useQueryDialog } from '@/hooks/useQueryDialogue'; 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 Schema = z.object({ query: z.string().min(1) }); + const router = useRouter(); + const { mode } = useColorScheme(); + const [isLoading, setIsLoading] = useState(false); + const methods = useForm>({ + resolver: zodResolver(Schema), + defaultValues: {}, }); + const { refreshDialogList } = useQueryDialog(); + const submit = async ({ query }: z.infer) => { + try { + setIsLoading(true); + methods.reset(); + const res = await sendPostRequest('/v1/chat/dialogue/new', { + chat_mode: 'chat_normal' + }); + if (res?.success && res?.data?.conv_uid) { + // router.push(`/agents/${res?.data?.conv_uid}?newMessage=${query}`); + // await refreshDialogList(); + } + } catch (err) { + } finally { + setIsLoading(false); + } + }; - const handleGetD = () => { - sendGetRequest('/v1/chat/dialogue/list', { - }) - } - - useEffect(() => { - handleGetD(); - }, []); return ( -
- - [DB-GPT](https://github.com/csunny/DB-GPT) 是一个开源的以数据库为基础的GPT实验项目,使用本地化的GPT大模型与您的数据和环境进行交互,无数据泄露风险,100% 私密,100% 安全。 - - .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 - } - }} - > - ( -
- + <> +
+
+ + + + +
+
+
+
+
+

Scenes

+
+ + + +
- )} - 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 ( - - -
- Databerry - - 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 7e3ebae6c..caff46e2e 100644 --- a/datacenter/package-lock.json +++ b/datacenter/package-lock.json @@ -23,6 +23,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", @@ -30,6 +31,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", @@ -46,6 +48,7 @@ "zod": "^3.19.1" }, "devDependencies": { + "@types/lodash": "^4.14.195", "@types/nprogress": "^0.2.0" } }, @@ -2183,11 +2186,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", @@ -2382,6 +2396,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", @@ -4464,6 +4506,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", @@ -4754,6 +4801,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", @@ -4916,7 +4968,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": { @@ -7206,6 +7258,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", @@ -9703,11 +9763,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", @@ -9864,6 +9935,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", @@ -11546,6 +11639,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", @@ -11763,6 +11861,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", @@ -11889,7 +11992,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": { @@ -13687,6 +13790,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 5498489b6..e2b0b793e 100644 --- a/datacenter/package.json +++ b/datacenter/package.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", @@ -47,6 +49,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