From 40766106d851a455453af2a440207d7b224244a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=A6=82=E5=A8=81?= Date: Sun, 4 Jan 2026 13:26:12 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=8A=BD=E7=A6=BB=20inputbar?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Custom/InputBar/index.less | 17 +++ src/components/Custom/InputBar/index.tsx | 140 ++++++++++++++++++++++ src/pages/Welcome.tsx | 121 ++----------------- src/pages/chat/index.less | 8 ++ src/pages/chat/index.tsx | 8 +- 5 files changed, 178 insertions(+), 116 deletions(-) create mode 100644 src/components/Custom/InputBar/index.less create mode 100644 src/components/Custom/InputBar/index.tsx diff --git a/src/components/Custom/InputBar/index.less b/src/components/Custom/InputBar/index.less new file mode 100644 index 0000000..bc080a6 --- /dev/null +++ b/src/components/Custom/InputBar/index.less @@ -0,0 +1,17 @@ +.InputBar { + .CenterCard { + width: 50vw; + padding: 18px 18px 0 18px; + background-color: white; + border-radius: 8px; + padding-bottom: 24px, + } + + .Flex { + flex: 1; + + .ant-form-item { + --ant-form-item-margin-bottom: 0; + } + } +} \ No newline at end of file diff --git a/src/components/Custom/InputBar/index.tsx b/src/components/Custom/InputBar/index.tsx new file mode 100644 index 0000000..a7d8e2c --- /dev/null +++ b/src/components/Custom/InputBar/index.tsx @@ -0,0 +1,140 @@ +import { ProForm, ProFormTextArea } from '@ant-design/pro-components'; +import { useModel, history } from '@umijs/max'; +import { Button, Divider, Dropdown, Flex, message, Tag, theme } from 'antd'; +import React, { useRef, useState } from 'react'; +import './index.less' +import { FileSearchOutlined, GlobalOutlined, PlusOutlined } from '@ant-design/icons'; +import { TweenOneGroup } from 'rc-tween-one'; + +export type InputBarEvent = { + query: string; + tools: Object[]; +} + +export type InputBarSubmitHandler = (event: InputBarEvent) => void; + +export type InputBarProps = { + onSubmit?: InputBarSubmitHandler; +} + +export const InputBarToolItems = [{ + key: 'searchWeb', + label: '搜索网站', + color: '#55acee', + icon: , +}, { + key: 'searchKB', + label: '知识库', + color: '#55acee', + icon: , + children: [ + { key: 'searchKB_kb1', label: '知识库1' }, + { key: 'searchKB_kb2', label: '知识库2' }, + { type: 'divider' }, + { key: 'searchKB_add', label: '新增知识库' }, + ], +}] + +const tagGroupStyle: React.CSSProperties = { + display: 'flex', + alignItems: 'center', + flexWrap: 'wrap', + gap: 8, + marginBottom: 8, + marginTop: 16, +}; + +const InputBar = (props: InputBarProps) => { + const textAreaRef = useRef(null); + const [tools, setTools] = useState([]); + const textAreaFieldProps: any = { + ref: textAreaRef, + autoSize: { + minRows: 1, + maxRows: 5, + }, + variant: 'borderless', + onPressEnter: (e: any) => { + const { nativeEvent: { shiftKey, key } } = e; + if (shiftKey && key === "Enter") { + const { current: { resizableTextArea: { textArea } } } = textAreaRef; + e.preventDefault(); + const text = textArea?.value; + console.log({ + query: text, + tools: tools, + }); + props?.onSubmit && props.onSubmit({ + query: text, + tools: tools?.map((e:any) => e.key), + }) + textArea.value = ""; + } + } + } + + const itemOnClick = ({ key }: any) => { + if (key === 'searchKB_add') { + message.info("创建知识库") + return; + } + const toolsKeys: string[] = tools?.map((e: any) => e.key); + if (toolsKeys?.includes(key)) { + setTools(tools.filter((e: any) => e.key !== key)); + return; + } + if (key.includes('kb')) { + const kbObj = InputBarToolItems?.find(i => i.key === 'searchKB') + const obj = kbObj?.children?.find(i => i.key === key); + setTools([{ ...obj, icon: kbObj?.icon }, ...tools]); + } else { + const obj = InputBarToolItems?.find(i => i.key === key); + setTools([obj, ...tools]); + } + } + + const Tags = () => { + if (tools?.length) { + return (<> + + { + if (e.type === 'appear' || e.type === 'enter') { + (e.target as any).style = 'display: inline-block'; + } + }} + > + {tools?.map((e: any) => itemOnClick({ key: e.key })}> + {e.label} + )} + + + ) + } + return <> + } + + return ( +
+
+ + + + + +
+ +
+
+
+ +
+
+ ); +}; + +export default InputBar; diff --git a/src/pages/Welcome.tsx b/src/pages/Welcome.tsx index f9d213d..4bc1445 100644 --- a/src/pages/Welcome.tsx +++ b/src/pages/Welcome.tsx @@ -1,129 +1,24 @@ -import { PageContainer, ProForm, ProFormTextArea } from '@ant-design/pro-components'; -import { useModel, history } from '@umijs/max'; -import { Button, Divider, Dropdown, Flex, message, Tag, theme } from 'antd'; -import React, { useRef, useState } from 'react'; +import { PageContainer } from '@ant-design/pro-components'; +import { useModel } from '@umijs/max'; +import { Flex, theme } from 'antd'; +import React, { useState } from 'react'; import './Welcome.less' -import { FileSearchOutlined, GlobalOutlined, PlusOutlined } from '@ant-design/icons'; -import { TweenOneGroup } from 'rc-tween-one'; import HeaderModelSelect from '@/components/Custom/HeaderModelSelect'; import type { ModelItem } from '@/components/Custom/HeaderModelSelect'; - -const tagGroupStyle: React.CSSProperties = { - display: 'flex', - alignItems: 'center', - flexWrap: 'wrap', - gap: 8, - marginBottom: 8, - marginTop: 16, -}; - +import InputBar from '@/components/Custom/InputBar'; const Welcome: React.FC = () => { const { token } = theme.useToken(); const { initialState } = useModel('@@initialState'); - const textAreaRef = useRef(null); - const [tools, setTools] = useState([]); const [model, setModel] = useState(undefined); - const textAreaFieldProps: any = { - ref: textAreaRef, - autoSize: { - minRows: 1, - maxRows: 5, - }, - variant: 'borderless', - onPressEnter: (e: any) => { - const { nativeEvent: { shiftKey, key } } = e; - if (shiftKey && key === "Enter") { - const { current: { resizableTextArea: { textArea } } } = textAreaRef; - e.preventDefault(); - const text = textArea?.value; - console.log(text); - textArea.value = ""; - history.push('/chat'); - } - } - } - - const items = [{ - key: 'searchWeb', - label: '搜索网站', - color: '#55acee', - icon: , - }, { - key: 'searchKB', - label: '知识库', - color: '#55acee', - icon: , - children: [ - { key: 'searchKB_kb1', label: '知识库1' }, - { key: 'searchKB_kb2', label: '知识库2' }, - { type: 'divider' }, - { key: 'searchKB_add', label: '新增知识库' }, - ], - }] - - const itemOnClick = ({ key }: any) => { - if (key === 'searchKB_add') { - message.info("创建知识库") - return; - } - const toolsKeys: string[] = tools?.map((e: any) => e.key); - if (toolsKeys?.includes(key)) { - setTools(tools.filter((e: any) => e.key !== key)); - return; - } - if (key.includes('kb')) { - const kbObj = items?.find(i => i.key === 'searchKB') - const obj = kbObj?.children?.find(i => i.key === key); - setTools([{ ...obj, icon: kbObj?.icon }, ...tools]); - } else { - const obj = items?.find(i => i.key === key); - setTools([obj, ...tools]); - } - } - - const Tags = () => { - if (tools?.length) { - return (<> - - { - if (e.type === 'appear' || e.type === 'enter') { - (e.target as any).style = 'display: inline-block'; - } - }} - > - {tools?.map((e: any) => itemOnClick({ key: e.key })}> - {e.label} - )} - - - ) - } - return <> - } return ( setModel(e)}/>} className='WelcomePage'>
-
- - - - - -
- -
-
-
- -
+ { + console.log(e); + }}/>
); diff --git a/src/pages/chat/index.less b/src/pages/chat/index.less index 0bd6538..da4ced6 100644 --- a/src/pages/chat/index.less +++ b/src/pages/chat/index.less @@ -2,4 +2,12 @@ .Flex { flex: 1; } + + .CenterCard { + width: 50vw; + padding: 18px 18px 0 18px; + background-color: white; + border-radius: 8px; + padding-bottom: 24px, + } } \ No newline at end of file diff --git a/src/pages/chat/index.tsx b/src/pages/chat/index.tsx index d730411..dd9ac4d 100644 --- a/src/pages/chat/index.tsx +++ b/src/pages/chat/index.tsx @@ -1,20 +1,22 @@ -import { PageContainer } from '@ant-design/pro-components'; +import { PageContainer, ProForm, ProFormTextArea } from '@ant-design/pro-components'; import type { ModelItem } from '@/components/Custom/HeaderModelSelect'; import './index.less'; import { useState } from 'react'; import HeaderModelSelect from '@/components/Custom/HeaderModelSelect'; -import { Flex } from 'antd'; +import { Button, Dropdown, Flex } from 'antd'; export default () => { const [model, setModel] = useState(undefined); + return setModel(val)} />} >
- +
+
} \ No newline at end of file